mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-11 09:55:36 +00:00
Doc updates.
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.
This commit is contained in:
parent
e82e7b604a
commit
007cff6d75
26 changed files with 334 additions and 100 deletions
29
ChangeLog
29
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),
|
||||
|
|
|
@ -124,6 +124,15 @@ Atomic operations
|
|||
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
|
||||
-------
|
||||
|
|
106
docs/design/part-clocks.txt
Normal file
106
docs/design/part-clocks.txt
Normal file
|
@ -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.
|
||||
|
||||
|
|
@ -10,15 +10,20 @@
|
|||
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.
|
||||
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.
|
||||
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
|
||||
----
|
||||
|
|
|
@ -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
|
||||
---------------
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
||||
|
||||
|
|
26
gst/gstbin.c
26
gst/gstbin.c
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue