Doc updates.
authorWim Taymans <wim.taymans@gmail.com>
Thu, 10 Mar 2005 12:51:45 +0000 (12:51 +0000)
committerWim Taymans <wim.taymans@gmail.com>
Thu, 10 Mar 2005 12:51:45 +0000 (12:51 +0000)
Original commit message from CVS:
* docs/design/part-MT-refcounting.txt:
* docs/design/part-clocks.txt:
* docs/design/part-gstelement.txt:
* docs/design/part-gstobject.txt:
* docs/design/part-standards.txt:
* gst/gstbin.c: (gst_bin_add_func), (gst_bin_add),
(gst_bin_remove_func), (gst_bin_remove):
* gst/gstbin.h:
* gst/gstbuffer.c:
* gst/gstcaps.h:
* testsuite/clock/clock1.c: (main):
* testsuite/clock/clock2.c: (gst_clock_debug), (element_wait),
(main):
* testsuite/dlopen/loadgst.c: (do_test):
* testsuite/refcounting/bin.c: (add_remove_test1),
(add_remove_test2), (main):
* testsuite/refcounting/element.c: (main):
* testsuite/refcounting/element_pad.c: (main):
* testsuite/refcounting/pad.c: (main):
* tools/gst-launch.c: (sigint_handler_sighandler):
* tools/gst-typefind.c: (main):
Doc updates.
Added doc about clock.
removed gst_bin_iterate_recurse_up(), marked methods
for removal.
Fix more testsuites.

26 files changed:
ChangeLog
docs/design/part-MT-refcounting.txt
docs/design/part-clocks.txt [new file with mode: 0644]
docs/design/part-gstelement.txt
docs/design/part-gstobject.txt
docs/design/part-standards.txt
gst/gstbin.c
gst/gstbin.h
gst/gstbuffer.c
gst/gstcaps.h
tests/old/testsuite/clock/clock1.c
tests/old/testsuite/clock/clock2.c
tests/old/testsuite/dlopen/loadgst.c
tests/old/testsuite/refcounting/bin.c
tests/old/testsuite/refcounting/element.c
tests/old/testsuite/refcounting/element_pad.c
tests/old/testsuite/refcounting/pad.c
testsuite/clock/clock1.c
testsuite/clock/clock2.c
testsuite/dlopen/loadgst.c
testsuite/refcounting/bin.c
testsuite/refcounting/element.c
testsuite/refcounting/element_pad.c
testsuite/refcounting/pad.c
tools/gst-launch.c
tools/gst-typefind.c

index 2c03dfe..8423228 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,32 @@
+2005-03-10  Wim Taymans  <wim@fluendo.com>
+
+       * docs/design/part-MT-refcounting.txt:
+       * docs/design/part-clocks.txt:
+       * docs/design/part-gstelement.txt:
+       * docs/design/part-gstobject.txt:
+       * docs/design/part-standards.txt:
+       * gst/gstbin.c: (gst_bin_add_func), (gst_bin_add),
+       (gst_bin_remove_func), (gst_bin_remove):
+       * gst/gstbin.h:
+       * gst/gstbuffer.c:
+       * gst/gstcaps.h:
+       * testsuite/clock/clock1.c: (main):
+       * testsuite/clock/clock2.c: (gst_clock_debug), (element_wait),
+       (main):
+       * testsuite/dlopen/loadgst.c: (do_test):
+       * testsuite/refcounting/bin.c: (add_remove_test1),
+       (add_remove_test2), (main):
+       * testsuite/refcounting/element.c: (main):
+       * testsuite/refcounting/element_pad.c: (main):
+       * testsuite/refcounting/pad.c: (main):
+       * tools/gst-launch.c: (sigint_handler_sighandler):
+       * tools/gst-typefind.c: (main):
+       Doc updates.
+       Added doc about clock.
+       removed gst_bin_iterate_recurse_up(), marked methods
+       for removal.
+       Fix more testsuites.
+
 2005-03-09  Wim Taymans  <wim@fluendo.com>
 
        * gst/gstpad.c: (gst_pad_get_direction),
index 3d45064..27654dc 100644 (file)
@@ -123,6 +123,15 @@ Atomic operations
   Atomic operations are generally used for refcounting and for the allocation of
   small fixed size objects in a memchunk. They can also be used to implement a
   lockfree list or stack.
+
+Compare and swap
+
+  As part of the atomic operations, compare-and-swap (CAS) can be used to access
+  or update a single property or pointer in an object without having to take a
+  lock.
+
+  This technique is currently not used in GStreamer but might be added in the
+  future in performance critical places.
  
 
 Objects
diff --git a/docs/design/part-clocks.txt b/docs/design/part-clocks.txt
new file mode 100644 (file)
index 0000000..feb23f8
--- /dev/null
@@ -0,0 +1,106 @@
+Clocks
+------
+
+To synchronize the different elements, the GstPipeline is responsible for
+selecting and distributing a global GstClock for all the elements in it.
+
+This selection happens whenever an element is added or removed from the 
+pipeline. Whever the clock changes in a pipeline, a message is posted on
+the bus signaling the new clock to the application.
+
+The GstClock returns a monotonically increasing time with the method 
+_get_time(). Its accuracy and base time depends on the specific clock 
+implementation but time is always expessed in nanoseconds. Since the
+baseline of the clock is undefined, the clock time returned is not
+meaningfull in itself, what matters are the deltas between two clock
+times.
+The time reported by the clock is called the absolute time.
+
+
+Time in GStreamer
+-----------------
+
+The absolute time is used to calculate the stream time. The stream time
+is defined as follows:
+
+ - If the pipeline is NULL/READY, the stream time is undefined.
+ - In PAUSED, the stream time remains at the time when it was last 
+   PAUSED. When the stream is PAUSED for the first time, the stream time
+   is 0. 
+ - In PLAYING, the stream time is the delta between the absolute time
+   and the base time. The base time is defined as the absolute time minus
+   the stream time at the time when the pipeline is set to PLAYING.
+ - after a seek, the stream time is set to seek time.
+
+The stream time is completely managed by the GstPipeline object using the
+GstClock absolute time.
+
+
+Timestamps
+----------
+
+Timestamps on buffers are always expressed in stream time. This means that
+all elements that require synchronizing to the clock need to be aware of
+the clock base time in order to know the absolute time of the timestamp.
+Converting a timestamp (in stream time) to absolute time is performed using
+the following formula:
+
+    AT = BT + ST               where: AT = absolute time
+                                      BT = base time
+                                      ST = stream time
+
+The pipeline base time is propagated to all the element during the PAUSED
+to PLAYING state change. All elements are therefore able to convert the 
+stream time to the absolute time. It is possible to specify an aditional
+delay to the base time to compensate for the delay it takes to perform
+the state change.
+
+
+Clock features
+--------------
+
+The clock supports periodic and single shot clock notifications both
+synchronous and asynchronous.
+
+One first needs to create a GstClockID for the periodic or single shot
+notification using _clock_new_single_shot_id() or _clock_new_periodic_id().
+
+To perform a blocking wait for the specific time of the GstClockID use the
+gst_clock_id_wait(). To receive a callback when the specific time is reached
+in the clock use gst_clock_id_wait_async(). Both these calls can be interrupted
+with the gst_clock_id_unschedule() call. If the blocking wait is unscheduled
+a return value of GST_CLOCK_UNSCHEDULED is returned.
+
+The async callbacks can happen from any thread, either provided by the
+core or from a streaming thread. The application should be prepared for this.
+
+A GstClockID that has been unscheduled cannot be used again for any wait
+operation. 
+
+It is possible to perform a blocking wait on the same ID from multiple 
+threads. However, registering the same ID for multiple async notifications is 
+not possible, the callback will only be called once.
+
+None of the wait operations unref the GstClockID, the application is 
+responsible for unreffing the ids itself. This holds for both periodic and
+single shot notifications. 
+
+These clock operations do not operate on the stream time, so the callbacks
+will also occur when not in PLAYING state as if the clock just keeps on 
+running.
+
+
+Clock implementations
+---------------------
+
+The GStreamer core provides a GstSystemClock based on the system time. 
+Asynchronous callbacks are scheduled from an internal thread.
+
+Clock implementors are encouraged to subclass this systemclock as it
+implements the async notification.
+
+Subclasses can however override all of the important methods for sync and
+async notifications to implement their own callback methods or blocking
+wait operations. 
+
+
index 9cb57ec..139bf65 100644 (file)
 GstElement
 ==========
 
-The Element is the most important object in the entire GStreamer system, as it defines the structure of the pipeline.  
-Elements include sources, filters, sinks, and containers (Bins).  They may be an intrinsic part of the core GStreamer
-library, or may be loaded from a plugin.  In some cases they're even fabricated from completely different systems (see
-the LADSPA plugin).  They are generally created from a GstElementFactory, which will be covered in another chapter, but
-for the intrinsic types they can be created with specific functions.
-
-Elements contains GstPads (also covered in another chapter), which are subsequently used to connect the Elements
-together to form a pipeline capable of passing and processing data.  They have a parent, which must be another Element.  
-This allows deeply nested pipelines, and the possibility of "black-box" meta-elements.
+The Element is the most important object in the entire GStreamer system, as it
+defines the structure of the pipeline.  Elements include sources, filters,
+sinks, and containers (Bins).  They may be an intrinsic part of the core
+GStreamer library, or may be loaded from a plugin.  In some cases they're even
+fabricated from completely different systems (see the LADSPA plugin).  They
+are generally created from a GstElementFactory, which will be covered in
+another chapter, but for the intrinsic types they can be created with specific
+functions.
+
+Elements contains GstPads (also covered in another chapter), which are
+subsequently used to connect the Elements together to form a pipeline capable
+of passing and processing data.  They have a parent, which must be another
+Element.  This allows deeply nested pipelines, and the possibility of
+"black-box" meta-elements.
 
 Name
 ----
index 9e1d9f8..093f2f5 100644 (file)
@@ -50,6 +50,9 @@ The GstObject contains the necessary primitives to lock the object in a
 thread-safe manner.  This will be used to provide general thread-safety as
 needed.  However, this lock is generic, i.e. it covers the whole object.
 
+The object LOCK is a very lowlevel lock that should only be held to access
+the object properties for short periods of code.
+
 All members of the GstObject structure marked as
 /*< public >*/ /* with LOCK */
 are protected by this lock.  These members can only be accessed for reading
@@ -66,6 +69,20 @@ reasonable, since they are the only possible things to protect in the
 GstObject.
 
 
+Locking order
+-------------
+
+In parent-child situations the lock of the parent must always be taken first
+before taking the lock of the child. It is NOT allowed to hold the child
+lock before taking the parent lock.
+
+This policy allows for parents to iterate their children and setting properties
+on them.
+
+Whenever a nested lock needs to be taken on objects not involved in a 
+parent-child relation (eg. pads), an explictic locking order has to be defined.
+
+
 Path Generation
 ---------------
 
index 27eac4c..37eaf3d 100644 (file)
@@ -1,12 +1,54 @@
 Ownership of dynamic objects
 ----------------------------
 
-Any object-oriented system or language that doesn't have automatic garbage collection has many potential pitfalls as 
-far as the pointers go.  Therefore, some standards must be adhered to as far as who owns what.
+Any object-oriented system or language that doesn't have automatic garbage 
+collection has many potential pitfalls as far as the pointers go. Therefore, 
+some standards must be adhered to as far as who owns what.
 
-Strings:
-Arguments passed into a function are owned by the caller, and the function will make a copy of the string for its own 
-internal use.  The string should be const gchar *.  Strings returned from a function are always a copy of the
+Strings
+-------
+
+Arguments passed into a function are owned by the caller, and the function 
+will make a copy of the string for its own internal use.  The string should 
+be const gchar *.  Strings returned from a function are always a copy of the
 original and should be freed after usage by the caller.
 
-Objects:
+  ex:
+
+     name = gst_element_get_name (element);   /* copy of name is made */
+     .. use name ..
+     g_free (name);                           /* free after usage */
+
+
+Objects
+-------
+
+Objects passed into a function are owned by the caller, any additional 
+reference held to the object after leaving the function should increase the 
+refcount of that object. 
+
+Objects returned from a function are owned by the caller. This means that the
+called should _free() or _unref() the object after usage.
+
+  ex:
+
+     peer = gst_pad_get_peer (pad);          /* peer with increased refcount */
+     if (peer) {
+       .. use peer ..
+       gst_object_unref (GST_OBJECT (peer)); /* unref peer after usage */
+     }
+
+
+Iterators
+---------
+
+When retrieving multiple objects from an object an iterator should be used.
+The iterator allows you to access the objects one after another while making
+sure that the set of objects retrieved remains consistent.
+
+Each object retrieved from an iterator has its refcount increased or is a
+copy of the original. In any case the object should be unreffed or freed
+after usage.
+
+
+
index 70d15b1..c433bef 100644 (file)
@@ -300,6 +300,7 @@ gst_bin_get_clock_func (GstElement * element)
   return result;
 }
 
+/* will be removed */
 static void
 gst_bin_set_element_sched (GstElement * element, GstScheduler * sched)
 {
@@ -359,6 +360,7 @@ gst_bin_set_element_sched (GstElement * element, GstScheduler * sched)
   }
 }
 
+/* will be removed */
 static void
 gst_bin_unset_element_sched (GstElement * element, GstScheduler * sched)
 {
@@ -452,8 +454,8 @@ gst_bin_add_func (GstBin * bin, GstElement * element)
     goto duplicate_name;
 
   /* set the element's parent and add the element to the bin's list of children */
-  if (G_UNLIKELY (!gst_object_set_parent (GST_OBJECT (element),
-              GST_OBJECT (bin))))
+  if (G_UNLIKELY (!gst_object_set_parent (GST_OBJECT_CAST (element),
+              GST_OBJECT_CAST (bin))))
     goto had_parent;
 
   bin->children = g_list_prepend (bin->children, element);
@@ -573,12 +575,12 @@ gst_bin_remove_func (GstBin * bin, GstElement * element)
 
   /* we ref here because after the _unparent() the element can be disposed
    * and we still need it to fire a signal. */
-  gst_object_ref (GST_OBJECT (element));
-  gst_object_unparent (GST_OBJECT (element));
+  gst_object_ref (GST_OBJECT_CAST (element));
+  gst_object_unparent (GST_OBJECT_CAST (element));
 
   g_signal_emit (G_OBJECT (bin), gst_bin_signals[ELEMENT_REMOVED], 0, element);
   /* element is really out of our control now */
-  gst_object_unref (GST_OBJECT (element));
+  gst_object_unref (GST_OBJECT_CAST (element));
 
   return TRUE;
 
@@ -731,12 +733,6 @@ gst_bin_iterate_recurse (GstBin * bin)
   return result;
 }
 
-GstIterator *
-gst_bin_iterate_recurse_up (GstBin * bin)
-{
-  return NULL;
-}
-
 /* returns 0 if the element is a sink, this is made so that
  * we can use this function as a filter 
  *
@@ -820,6 +816,8 @@ bin_element_is_sink (GstElement * child, GstBin * bin)
  * Each element will have its refcount increased, so unref 
  * after usage.
  *
+ * The sink elements are those without any linked srcpads.
+ *
  * Returns: a #GstIterator of #GstElements. gst_iterator_free after use.
  *
  * MT safe.
@@ -848,6 +846,8 @@ gst_bin_iterate_sinks (GstBin * bin)
  *
  * An internal function to inform the parent bin about a state change
  * of a child.
+ *
+ * Marked for removal.
  */
 void
 gst_bin_child_state_change (GstBin * bin, GstElementState oldstate,
@@ -873,6 +873,7 @@ gst_bin_child_state_change (GstBin * bin, GstElementState oldstate,
   }
 }
 
+/* will be removed */
 static void
 gst_bin_child_state_change_func (GstBin * bin, GstElementState oldstate,
     GstElementState newstate, GstElement * child)
@@ -937,6 +938,8 @@ typedef gboolean (*GstBinForeachFunc) (GstBin * bin, GstElement * element,
  * called, and that are still in @bin when the child is reached.
  *
  * Returns: TRUE if @func always returned TRUE, FALSE otherwise
+ *
+ * Marked for removal.
  **/
 static gboolean
 gst_bin_foreach (GstBin * bin, GstBinForeachFunc func, gpointer data)
@@ -1283,6 +1286,7 @@ gst_bin_get_by_interface (GstBin * bin, GType interface)
  *
  * Returns: An iterator for the  elements inside the bin implementing the interface.
  *
+ * MT safe.
  */
 GstIterator *
 gst_bin_iterate_all_by_interface (GstBin * bin, GType interface)
index 7dfbe18..c6ab722 100644 (file)
@@ -129,7 +129,6 @@ GstElement* gst_bin_get_by_interface         (GstBin *bin, GType interface);
 /* retrieve multiple children */
 GstIterator*    gst_bin_iterate_elements        (GstBin *bin);
 GstIterator*    gst_bin_iterate_recurse                 (GstBin *bin);
-GstIterator*    gst_bin_iterate_recurse_up      (GstBin *bin);
 
 GstIterator*   gst_bin_iterate_sinks            (GstBin *bin);
 GstIterator*   gst_bin_iterate_all_by_interface (GstBin *bin, GType interface);
index af4c87e..fd3fead 100644 (file)
@@ -271,7 +271,8 @@ gst_buffer_new_and_alloc (guint size)
  * Returns: the #GstCaps, or NULL if there was an error or there
  * were no caps on this buffer.
  */
-/* FIXME can we make this threadsafe without a lock on the buffer? */
+/* FIXME can we make this threadsafe without a lock on the buffer?
+ * We can use compare and swap and atomic reads. */
 GstCaps *
 gst_buffer_get_caps (GstBuffer * buffer)
 {
@@ -289,7 +290,10 @@ gst_buffer_get_caps (GstBuffer * buffer)
  * be increased and any previous caps on the buffer will be
  * unreffed.
  */
-/* FIXME can we make this threadsafe without a lock on the buffer? */
+/* FIXME can we make this threadsafe without a lock on the buffer? 
+ * We can use compare and swap and atomic reads. Another idea is to
+ * not attach the caps to the buffer but use an event to signal a caps
+ * change. */
 void
 gst_buffer_set_caps (GstBuffer * buffer, GstCaps * caps)
 {
index 84eb920..e0c21f7 100644 (file)
@@ -148,13 +148,6 @@ void                     gst_caps_replace                               (GstCaps
 gchar *                  gst_caps_to_string                             (const GstCaps *caps);
 GstCaps *                gst_caps_from_string                           (const gchar   *string);
 
-gboolean                 gst_caps_structure_fixate_field_nearest_int    (GstStructure *structure,
-                                                                        const char   *field_name,
-                                                                        int           target);
-gboolean                 gst_caps_structure_fixate_field_nearest_double (GstStructure *structure,
-                                                                        const char   *field_name,
-                                                                        double        target);
-
 G_END_DECLS
 
 #endif /* __GST_CAPS_H__ */
index 7aa9856..2e26085 100644 (file)
@@ -43,13 +43,12 @@ main (int argc, char *argv[])
   gst_bin_add_many (GST_BIN (pipeline), src, id, sink, NULL);
   gst_element_link_many (src, id, sink, NULL);
 
-  clock = gst_bin_get_clock (GST_BIN (pipeline));
+  clock = gst_pipeline_get_clock (GST_PIPELINE (pipeline));
   g_assert (clock != NULL);
   gst_clock_debug (clock);
   gst_clock_debug (clock);
 
   gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
-  gst_bin_iterate (GST_BIN (pipeline));
   gst_clock_debug (clock);
   gst_clock_debug (clock);
   gst_clock_debug (clock);
index 303b9c2..8271291 100644 (file)
@@ -7,12 +7,26 @@
  */
 
 #include <gst/gst.h>
+
 void
 gst_clock_debug (GstClock * clock, GstElement * fakesink)
 {
-  g_print ("Clock info: time %" G_GUINT64_FORMAT " - Element info: time %"
-      G_GUINT64_FORMAT "\n", gst_clock_get_time (clock),
-      gst_element_get_time (fakesink));
+  GstClockTime time;
+
+  time = gst_clock_get_time (clock);
+
+  g_print ("Clock info: time %" G_GUINT64_FORMAT " Element %" GST_TIME_FORMAT
+      "\n", time, GST_TIME_ARGS (time - fakesink->base_time));
+}
+
+static void
+element_wait (GstElement * element, GstClockTime time)
+{
+  GstClockID id;
+
+  id = gst_clock_new_single_shot_id (clock, time + element->base_time);
+  gst_clock_id_wait (id, NULL);
+  gst_clock_id_unref (id);
 }
 
 int
@@ -41,10 +55,10 @@ main (int argc, char *argv[])
   g_usleep (G_USEC_PER_SEC);
   gst_clock_debug (clock, fakesink);
 
-  gst_element_wait (fakesink, 2 * GST_SECOND);
+  element_wait (fakesink, 2 * GST_SECOND);
   gst_clock_debug (clock, fakesink);
 
-  gst_element_wait (fakesink, 5 * GST_SECOND);
+  element_wait (fakesink, 5 * GST_SECOND);
   gst_clock_debug (clock, fakesink);
 
   g_usleep (G_USEC_PER_SEC);
index 9bfbd0a..59d6e72 100644 (file)
@@ -7,22 +7,20 @@ do_test (void)
 {
   GstElement *pipeline;
   int i;
-  gboolean ret;
 
   gst_init (NULL, NULL);
 
   pipeline = gst_parse_launch ("fakesrc ! fakesink", NULL);
   g_assert (pipeline != NULL);
 
-
   gst_element_set_state (pipeline, GST_STATE_PLAYING);
 
   for (i = 0; i < 100; i++) {
-    ret = gst_bin_iterate (GST_BIN (pipeline));
-    g_assert (ret);
+    g_usleep (1000);
     g_print ("%s", (i & 1) ? "+" : "-");
   }
   g_print ("\n");
 
+  gst_element_set_state (pipeline, GST_STATE_NULL);
   gst_object_unref (GST_OBJECT (pipeline));
 }
index 4d437b2..5d50268 100644 (file)
@@ -50,9 +50,9 @@ add_remove_test1 (void)
   bin = gst_bin_new ("testbin");
   element = gst_element_factory_make ("fakesrc", NULL);
   gst_element_set_name (element, "test1");
-  g_assert (GST_OBJECT_FLOATING (element));
+  g_assert (GST_OBJECT_IS_FLOATING (element));
   gst_bin_add (GST_BIN (bin), element);
-  g_assert (!GST_OBJECT_FLOATING (element));
+  g_assert (!GST_OBJECT_IS_FLOATING (element));
   gst_bin_remove (GST_BIN (bin), element);
 
   gst_object_unref (GST_OBJECT (bin));
@@ -68,16 +68,16 @@ add_remove_test2 (void)
   element = gst_element_factory_make ("fakesrc", NULL);
   gst_element_set_name (element, "test1");
   gst_object_ref (GST_OBJECT (element));
-  g_assert (GST_OBJECT_FLOATING (element));
+  g_assert (GST_OBJECT_IS_FLOATING (element));
   gst_bin_add (GST_BIN (bin), element);
-  g_assert (!GST_OBJECT_FLOATING (element));
+  g_assert (!GST_OBJECT_IS_FLOATING (element));
   gst_bin_remove (GST_BIN (bin), element);
-  g_assert (!GST_OBJECT_FLOATING (element));
-  g_assert (!GST_OBJECT_DESTROYED (element));
+  g_assert (!GST_OBJECT_IS_FLOATING (element));
+  g_assert (!GST_OBJECT_IS_DESTROYED (element));
 
   gst_object_unref (GST_OBJECT (element));
 #if 0
-  g_assert (GST_OBJECT_DESTROYED (element));
+  g_assert (GST_OBJECT_IS_DESTROYED (element));
   gst_object_unref (GST_OBJECT (element));
 #endif
 
@@ -169,10 +169,10 @@ main (int argc, gchar * argv[])
       gst_alloc_trace_live_all () - usage1);
 
   bin = gst_bin_new ("somebin");
-  g_assert (GST_OBJECT_FLOATING (bin));
+  g_assert (GST_OBJECT_IS_FLOATING (bin));
   gst_object_ref (GST_OBJECT (bin));
   gst_object_sink (GST_OBJECT (bin));
-  g_assert (!GST_OBJECT_FLOATING (bin));
+  g_assert (!GST_OBJECT_IS_FLOATING (bin));
   gst_object_unref (GST_OBJECT (bin));
   g_print ("create/ref/sink/unref new bin %d\n",
       gst_alloc_trace_live_all () - usage1);
@@ -188,10 +188,10 @@ main (int argc, gchar * argv[])
       gst_alloc_trace_live_all () - usage1);
 
   bin = gst_bin_new ("somebin");
-  g_assert (!GST_OBJECT_DESTROYED (bin));
+  g_assert (!GST_OBJECT_IS_DESTROYED (bin));
   gst_object_unref (GST_OBJECT (bin));
 #if 0
-  g_assert (GST_OBJECT_DESTROYED (bin));
+  g_assert (GST_OBJECT_IS_DESTROYED (bin));
   gst_object_unref (GST_OBJECT (bin));
 #endif
   g_print ("create/destroy/unref new bin %d\n",
index ed0258c..e4673bf 100644 (file)
@@ -35,10 +35,10 @@ main (int argc, gchar * argv[])
       gst_alloc_trace_live_all () - usage1);
 
   element = gst_element_factory_make ("fakesrc", NULL);
-  g_assert (GST_OBJECT_FLOATING (element));
+  g_assert (GST_OBJECT_IS_FLOATING (element));
   gst_object_ref (GST_OBJECT (element));
   gst_object_sink (GST_OBJECT (element));
-  g_assert (!GST_OBJECT_FLOATING (element));
+  g_assert (!GST_OBJECT_IS_FLOATING (element));
   gst_object_unref (GST_OBJECT (element));
   g_print ("create/ref/sink/unref new element %d\n",
       gst_alloc_trace_live_all () - usage1);
@@ -55,9 +55,9 @@ main (int argc, gchar * argv[])
 
 #if 0
   element = gst_element_factory_make ("fakesrc", NULL);
-  g_assert (!GST_OBJECT_DESTROYED (element));
+  g_assert (!GST_OBJECT_IS_DESTROYED (element));
   gst_object_unref (GST_OBJECT (element));
-  g_assert (GST_OBJECT_DESTROYED (element));
+  g_assert (GST_OBJECT_IS_DESTROYED (element));
   gst_object_unref (GST_OBJECT (element));
   g_print ("create/destroy/unref new element %d\n",
       gst_alloc_trace_live_all () - usage1);
index 24b4e82..2f3ad1d 100644 (file)
@@ -27,8 +27,8 @@ main (int argc, gchar * argv[])
   g_assert (GST_IS_ELEMENT (element));
   pad = gst_element_get_pad (element, "sink");
   g_assert (GST_IS_PAD (pad));
-  g_assert (GST_OBJECT_FLOATING (element));
-  g_assert (!GST_OBJECT_FLOATING (pad));
+  g_assert (GST_OBJECT_IS_FLOATING (element));
+  g_assert (!GST_OBJECT_IS_FLOATING (pad));
   g_assert (gst_pad_get_parent (pad) == element);
   gst_object_unref (GST_OBJECT (element));
   g_print ("create/addpad/unref 1 new element: %ld\n", vmsize () - usage1);
index 1b8d53e..fe9b001 100644 (file)
@@ -52,10 +52,10 @@ main (int argc, gchar * argv[])
   pad =
       gst_pad_new_from_template (gst_static_pad_template_get (&templ),
       "padname");
-  g_assert (GST_OBJECT_FLOATING (pad));
+  g_assert (GST_OBJECT_IS_FLOATING (pad));
   gst_object_ref (GST_OBJECT (pad));
   gst_object_sink (GST_OBJECT (pad));
-  g_assert (!GST_OBJECT_FLOATING (pad));
+  g_assert (!GST_OBJECT_IS_FLOATING (pad));
   gst_object_unref (GST_OBJECT (pad));
   g_print ("create/ref/sink/unref new pad %ld\n", vmsize () - usage1);
 
index 7aa9856..2e26085 100644 (file)
@@ -43,13 +43,12 @@ main (int argc, char *argv[])
   gst_bin_add_many (GST_BIN (pipeline), src, id, sink, NULL);
   gst_element_link_many (src, id, sink, NULL);
 
-  clock = gst_bin_get_clock (GST_BIN (pipeline));
+  clock = gst_pipeline_get_clock (GST_PIPELINE (pipeline));
   g_assert (clock != NULL);
   gst_clock_debug (clock);
   gst_clock_debug (clock);
 
   gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING);
-  gst_bin_iterate (GST_BIN (pipeline));
   gst_clock_debug (clock);
   gst_clock_debug (clock);
   gst_clock_debug (clock);
index 303b9c2..8271291 100644 (file)
@@ -7,12 +7,26 @@
  */
 
 #include <gst/gst.h>
+
 void
 gst_clock_debug (GstClock * clock, GstElement * fakesink)
 {
-  g_print ("Clock info: time %" G_GUINT64_FORMAT " - Element info: time %"
-      G_GUINT64_FORMAT "\n", gst_clock_get_time (clock),
-      gst_element_get_time (fakesink));
+  GstClockTime time;
+
+  time = gst_clock_get_time (clock);
+
+  g_print ("Clock info: time %" G_GUINT64_FORMAT " Element %" GST_TIME_FORMAT
+      "\n", time, GST_TIME_ARGS (time - fakesink->base_time));
+}
+
+static void
+element_wait (GstElement * element, GstClockTime time)
+{
+  GstClockID id;
+
+  id = gst_clock_new_single_shot_id (clock, time + element->base_time);
+  gst_clock_id_wait (id, NULL);
+  gst_clock_id_unref (id);
 }
 
 int
@@ -41,10 +55,10 @@ main (int argc, char *argv[])
   g_usleep (G_USEC_PER_SEC);
   gst_clock_debug (clock, fakesink);
 
-  gst_element_wait (fakesink, 2 * GST_SECOND);
+  element_wait (fakesink, 2 * GST_SECOND);
   gst_clock_debug (clock, fakesink);
 
-  gst_element_wait (fakesink, 5 * GST_SECOND);
+  element_wait (fakesink, 5 * GST_SECOND);
   gst_clock_debug (clock, fakesink);
 
   g_usleep (G_USEC_PER_SEC);
index 9bfbd0a..59d6e72 100644 (file)
@@ -7,22 +7,20 @@ do_test (void)
 {
   GstElement *pipeline;
   int i;
-  gboolean ret;
 
   gst_init (NULL, NULL);
 
   pipeline = gst_parse_launch ("fakesrc ! fakesink", NULL);
   g_assert (pipeline != NULL);
 
-
   gst_element_set_state (pipeline, GST_STATE_PLAYING);
 
   for (i = 0; i < 100; i++) {
-    ret = gst_bin_iterate (GST_BIN (pipeline));
-    g_assert (ret);
+    g_usleep (1000);
     g_print ("%s", (i & 1) ? "+" : "-");
   }
   g_print ("\n");
 
+  gst_element_set_state (pipeline, GST_STATE_NULL);
   gst_object_unref (GST_OBJECT (pipeline));
 }
index 4d437b2..5d50268 100644 (file)
@@ -50,9 +50,9 @@ add_remove_test1 (void)
   bin = gst_bin_new ("testbin");
   element = gst_element_factory_make ("fakesrc", NULL);
   gst_element_set_name (element, "test1");
-  g_assert (GST_OBJECT_FLOATING (element));
+  g_assert (GST_OBJECT_IS_FLOATING (element));
   gst_bin_add (GST_BIN (bin), element);
-  g_assert (!GST_OBJECT_FLOATING (element));
+  g_assert (!GST_OBJECT_IS_FLOATING (element));
   gst_bin_remove (GST_BIN (bin), element);
 
   gst_object_unref (GST_OBJECT (bin));
@@ -68,16 +68,16 @@ add_remove_test2 (void)
   element = gst_element_factory_make ("fakesrc", NULL);
   gst_element_set_name (element, "test1");
   gst_object_ref (GST_OBJECT (element));
-  g_assert (GST_OBJECT_FLOATING (element));
+  g_assert (GST_OBJECT_IS_FLOATING (element));
   gst_bin_add (GST_BIN (bin), element);
-  g_assert (!GST_OBJECT_FLOATING (element));
+  g_assert (!GST_OBJECT_IS_FLOATING (element));
   gst_bin_remove (GST_BIN (bin), element);
-  g_assert (!GST_OBJECT_FLOATING (element));
-  g_assert (!GST_OBJECT_DESTROYED (element));
+  g_assert (!GST_OBJECT_IS_FLOATING (element));
+  g_assert (!GST_OBJECT_IS_DESTROYED (element));
 
   gst_object_unref (GST_OBJECT (element));
 #if 0
-  g_assert (GST_OBJECT_DESTROYED (element));
+  g_assert (GST_OBJECT_IS_DESTROYED (element));
   gst_object_unref (GST_OBJECT (element));
 #endif
 
@@ -169,10 +169,10 @@ main (int argc, gchar * argv[])
       gst_alloc_trace_live_all () - usage1);
 
   bin = gst_bin_new ("somebin");
-  g_assert (GST_OBJECT_FLOATING (bin));
+  g_assert (GST_OBJECT_IS_FLOATING (bin));
   gst_object_ref (GST_OBJECT (bin));
   gst_object_sink (GST_OBJECT (bin));
-  g_assert (!GST_OBJECT_FLOATING (bin));
+  g_assert (!GST_OBJECT_IS_FLOATING (bin));
   gst_object_unref (GST_OBJECT (bin));
   g_print ("create/ref/sink/unref new bin %d\n",
       gst_alloc_trace_live_all () - usage1);
@@ -188,10 +188,10 @@ main (int argc, gchar * argv[])
       gst_alloc_trace_live_all () - usage1);
 
   bin = gst_bin_new ("somebin");
-  g_assert (!GST_OBJECT_DESTROYED (bin));
+  g_assert (!GST_OBJECT_IS_DESTROYED (bin));
   gst_object_unref (GST_OBJECT (bin));
 #if 0
-  g_assert (GST_OBJECT_DESTROYED (bin));
+  g_assert (GST_OBJECT_IS_DESTROYED (bin));
   gst_object_unref (GST_OBJECT (bin));
 #endif
   g_print ("create/destroy/unref new bin %d\n",
index ed0258c..e4673bf 100644 (file)
@@ -35,10 +35,10 @@ main (int argc, gchar * argv[])
       gst_alloc_trace_live_all () - usage1);
 
   element = gst_element_factory_make ("fakesrc", NULL);
-  g_assert (GST_OBJECT_FLOATING (element));
+  g_assert (GST_OBJECT_IS_FLOATING (element));
   gst_object_ref (GST_OBJECT (element));
   gst_object_sink (GST_OBJECT (element));
-  g_assert (!GST_OBJECT_FLOATING (element));
+  g_assert (!GST_OBJECT_IS_FLOATING (element));
   gst_object_unref (GST_OBJECT (element));
   g_print ("create/ref/sink/unref new element %d\n",
       gst_alloc_trace_live_all () - usage1);
@@ -55,9 +55,9 @@ main (int argc, gchar * argv[])
 
 #if 0
   element = gst_element_factory_make ("fakesrc", NULL);
-  g_assert (!GST_OBJECT_DESTROYED (element));
+  g_assert (!GST_OBJECT_IS_DESTROYED (element));
   gst_object_unref (GST_OBJECT (element));
-  g_assert (GST_OBJECT_DESTROYED (element));
+  g_assert (GST_OBJECT_IS_DESTROYED (element));
   gst_object_unref (GST_OBJECT (element));
   g_print ("create/destroy/unref new element %d\n",
       gst_alloc_trace_live_all () - usage1);
index 24b4e82..2f3ad1d 100644 (file)
@@ -27,8 +27,8 @@ main (int argc, gchar * argv[])
   g_assert (GST_IS_ELEMENT (element));
   pad = gst_element_get_pad (element, "sink");
   g_assert (GST_IS_PAD (pad));
-  g_assert (GST_OBJECT_FLOATING (element));
-  g_assert (!GST_OBJECT_FLOATING (pad));
+  g_assert (GST_OBJECT_IS_FLOATING (element));
+  g_assert (!GST_OBJECT_IS_FLOATING (pad));
   g_assert (gst_pad_get_parent (pad) == element);
   gst_object_unref (GST_OBJECT (element));
   g_print ("create/addpad/unref 1 new element: %ld\n", vmsize () - usage1);
index 1b8d53e..fe9b001 100644 (file)
@@ -52,10 +52,10 @@ main (int argc, gchar * argv[])
   pad =
       gst_pad_new_from_template (gst_static_pad_template_get (&templ),
       "padname");
-  g_assert (GST_OBJECT_FLOATING (pad));
+  g_assert (GST_OBJECT_IS_FLOATING (pad));
   gst_object_ref (GST_OBJECT (pad));
   gst_object_sink (GST_OBJECT (pad));
-  g_assert (!GST_OBJECT_FLOATING (pad));
+  g_assert (!GST_OBJECT_IS_FLOATING (pad));
   gst_object_unref (GST_OBJECT (pad));
   g_print ("create/ref/sink/unref new pad %ld\n", vmsize () - usage1);
 
index af0cb9b..bcda0bf 100644 (file)
@@ -221,7 +221,7 @@ fault_handler_sighandler (int signum)
   fault_spin ();
 }
 
-#else
+#else /* USE_SIGINFO */
 
 static void
 fault_handler_sigaction (int signum, siginfo_t * si, void *misc)
@@ -246,7 +246,7 @@ fault_handler_sigaction (int signum, siginfo_t * si, void *misc)
 
   fault_spin ();
 }
-#endif
+#endif /* USE_SIGINFO */
 
 static void
 fault_spin (void)
@@ -293,7 +293,7 @@ fault_setup (void)
   sigaction (SIGSEGV, &action, NULL);
   sigaction (SIGQUIT, &action, NULL);
 }
-#endif
+#endif /* DISABLE_FAULT_HANDLER */
 
 static void
 print_tag (const GstTagList * list, const gchar * tag, gpointer unused)
@@ -343,6 +343,8 @@ error_cb (GObject * object, GstObject * source, GError * error, gchar * debug)
 static void
 sigint_handler_sighandler (int signum)
 {
+  g_print ("Caught interrupt -- ");
+
   sigint_restore ();
 
   caught_intr = TRUE;
index 7ea6034..bf46343 100644 (file)
@@ -52,8 +52,10 @@ main (int argc, char *argv[])
   g_assert (GST_IS_ELEMENT (source));
   typefind = gst_element_factory_make ("typefind", "typefind");
   g_assert (GST_IS_ELEMENT (typefind));
-  gst_bin_add_many (GST_BIN (pipeline), source, typefind, NULL);
-  gst_element_link (source, typefind);
+  gst_bin_add (GST_BIN (pipeline), source);
+  gst_bin_add (GST_BIN (pipeline), typefind);
+  gst_pad_link (gst_element_get_pad (source, "src"),
+      gst_element_get_pad (typefind, "sink"));
   g_signal_connect (G_OBJECT (typefind), "have-type",
       G_CALLBACK (have_type_handler), NULL);