+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),
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
--- /dev/null
+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.
+
+
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
----
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
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
---------------
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.
+
+
+
return result;
}
+/* will be removed */
static void
gst_bin_set_element_sched (GstElement * element, GstScheduler * sched)
{
}
}
+/* will be removed */
static void
gst_bin_unset_element_sched (GstElement * element, GstScheduler * sched)
{
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);
/* 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;
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
*
* 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.
*
* 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,
}
}
+/* will be removed */
static void
gst_bin_child_state_change_func (GstBin * bin, GstElementState oldstate,
GstElementState newstate, GstElement * child)
* 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)
*
* 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)
/* 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);
* 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)
{
* 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)
{
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__ */
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);
*/
#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
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);
{
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));
}
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));
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
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);
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",
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);
#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);
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);
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);
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);
*/
#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
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);
{
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));
}
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));
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
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);
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",
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);
#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);
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);
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);
fault_spin ();
}
-#else
+#else /* USE_SIGINFO */
static void
fault_handler_sigaction (int signum, siginfo_t * si, void *misc)
fault_spin ();
}
-#endif
+#endif /* USE_SIGINFO */
static void
fault_spin (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)
static void
sigint_handler_sighandler (int signum)
{
+ g_print ("Caught interrupt -- ");
+
sigint_restore ();
caught_intr = TRUE;
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);