More state change fixes.

Original commit message from CVS:
More state change fixes.
Added/fixed some testcases.
Threadsafety fixes.
This commit is contained in:
Wim Taymans 2005-01-18 10:52:08 +00:00
parent 83156b4a9d
commit 864a9acf69
34 changed files with 1975 additions and 152 deletions

View file

@ -1,3 +1,65 @@
2005-01-18 Wim Taymans <wim@fluendo.com>
* docs/design/part-states.txt:
* gst/elements/gstfakesrc.c: (gst_fakesrc_loop),
(gst_fakesrc_activate):
* gst/elements/gstfilesrc.c: (gst_filesrc_getrange),
(gst_filesrc_open_file), (gst_filesrc_activate),
(filesrc_find_peek), (filesrc_find_suggest),
(gst_filesrc_type_find):
* gst/gstbin.c: (gst_bin_set_index), (gst_bin_set_clock),
(gst_bin_set_bus), (gst_bin_set_scheduler), (gst_bin_add_func),
(gst_bin_iterate_elements), (bin_element_is_sink),
(gst_bin_get_state), (gst_bin_change_state),
(gst_bin_get_by_name_recurse_up):
* gst/gstbus.c: (gst_bus_dispose), (gst_bus_new), (gst_bus_post),
(gst_bus_set_sync_handler), (gst_bus_create_watch), (bus_destroy),
(gst_bus_add_watch_full):
* gst/gstbus.h:
* gst/gstclock.c: (gst_clock_id_ref), (gst_clock_id_unref),
(gst_clock_id_compare_func), (gst_clock_id_wait),
(gst_clock_id_wait_async), (gst_clock_init), (gst_clock_get_time):
* gst/gstcpu.c: (_gst_cpu_initialize_i386), (gst_cpu_get_flags):
* gst/gstdata.c: (gst_data_is_writable), (gst_data_copy_on_write):
* gst/gstelement.c: (gst_element_class_init),
(gst_element_add_pad), (gst_element_remove_pad),
(gst_element_get_static_pad), (gst_element_is_locked_state),
(gst_element_get_state_func), (gst_element_abort_state),
(gst_element_set_state), (gst_element_pads_activate),
(gst_element_change_state), (gst_element_dispose),
(gst_element_finalize), (gst_element_get_scheduler):
* gst/gstelement.h:
* gst/gstobject.c: (gst_object_class_init), (gst_object_ref),
(gst_object_unref), (gst_object_sink), (gst_object_replace),
(gst_object_dispose), (gst_object_dispatch_properties_changed),
(gst_object_set_name), (gst_object_set_parent),
(gst_object_unparent), (gst_object_check_uniqueness),
(gst_object_get_path_string):
* gst/gstpad.h:
* gst/gstpipeline.c: (is_eos), (pipeline_bus_handler),
(gst_pipeline_change_state):
* gst/gstplugin.c:
* gst/gsttypes.h:
* gst/gstutils.c: (gst_element_finish_preroll),
(gst_element_get_compatible_pad_filtered),
(gst_element_state_get_name), (gst_element_link_pads_filtered),
(gst_element_unlink):
* testsuite/states/.cvsignore:
* testsuite/states/Makefile.am:
* testsuite/states/locked.c: (message_received), (main):
* testsuite/states/parent.c: (main):
* testsuite/states/test1.c: (message_received), (set_state),
(get_state), (commit_callback), (abort_callback), (main):
* testsuite/states/test2.c: (message_received), (set_state),
(get_state), (main):
* testsuite/states/test3.c: (message_received), (set_state),
(get_state), (main):
* testsuite/states/test4.c: (message_received), (set_state),
(get_state), (commit_callback), (abort_callback), (main):
More state change fixes.
Added/fixed some testcases.
Threadsafety fixes.
2005-01-12 Wim Taymans <wim@fluendo.com>
* gst/gstbin.c: (gst_bin_set_index), (gst_bin_set_clock),

View file

@ -59,7 +59,7 @@ The _set_state() function can return 3 possible values:
In the case of an async state change, it is not possible to proceed to the next
state until the current state change completed. After receiving an ASYNC return
value, you can use _element_get_state() to poll the status of the plugin.
value, you can use _element_get_state() to poll the status of the element.
When setting the state of an element, the PENDING_STATE is set to the required
state and the STATE_ERROR flag is cleared. Then the state change function of the

View file

@ -180,6 +180,7 @@ static gboolean gst_filesrc_srcpad_query (GstPad * pad, GstQueryType type,
static gboolean gst_filesrc_activate (GstPad * pad, GstActivateMode mode);
static GstElementStateReturn gst_filesrc_change_state (GstElement * element);
static GstCaps *gst_filesrc_type_find (GstFileSrc * src);
static void gst_filesrc_uri_handler_init (gpointer g_iface,
gpointer iface_data);
@ -854,6 +855,22 @@ gst_filesrc_open_file (GstFileSrc * src)
src->curoffset = 0;
GST_FLAG_SET (src, GST_FILESRC_OPEN);
{
GstCaps *caps;
guint64 offset;
guint length;
offset = src->curoffset;
length = src->block_size;
caps = gst_filesrc_type_find (src);
gst_pad_set_caps (src->srcpad, caps);
src->curoffset = offset;
src->block_size = length;
}
}
return TRUE;
}
@ -1122,6 +1139,89 @@ error:
return FALSE;
}
typedef struct
{
GstFileSrc *src;
guint best_probability;
GstCaps *caps;
GstBuffer *buffer;
}
FileSrcTypeFind;
static guint8 *
filesrc_find_peek (gpointer data, gint64 offset, guint size)
{
FileSrcTypeFind *find;
GstBuffer *buffer;
GstFileSrc *src;
if (size == 0)
return NULL;
find = (FileSrcTypeFind *) data;
src = find->src;
if (offset < 0) {
offset += src->filelen;
}
buffer = NULL;
gst_filesrc_getrange (src->srcpad, offset, size, &buffer);
if (find->buffer) {
gst_buffer_unref (find->buffer);
}
find->buffer = buffer;
return GST_BUFFER_DATA (buffer);
}
static void
filesrc_find_suggest (gpointer data, guint probability, const GstCaps * caps)
{
FileSrcTypeFind *find = (FileSrcTypeFind *) data;
if (probability > find->best_probability) {
gst_caps_replace (&find->caps, gst_caps_copy (caps));
find->best_probability = probability;
}
}
static GstCaps *
gst_filesrc_type_find (GstFileSrc * src)
{
GstTypeFind gst_find;
FileSrcTypeFind find;
GList *walk, *type_list = NULL;
GstCaps *result = NULL;
walk = type_list = gst_type_find_factory_get_list ();
find.src = src;
find.best_probability = 0;
find.caps = NULL;
gst_find.data = &find;
gst_find.peek = filesrc_find_peek;
gst_find.suggest = filesrc_find_suggest;
gst_find.get_length = NULL;
while (walk) {
GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (walk->data);
gst_type_find_factory_call_function (factory, &gst_find);
if (find.best_probability >= GST_TYPE_FIND_MAXIMUM)
break;
walk = g_list_next (walk);
}
if (find.best_probability > 0)
result = find.caps;
return result;
}
/*** GSTURIHANDLER INTERFACE *************************************************/
static guint

View file

@ -19,6 +19,8 @@
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
* MT safe.
*/
#include "gst_private.h"
@ -581,15 +583,31 @@ bin_element_is_sink (GstElement * child, GstBin * bin)
GList *pads;
gboolean connected_src = FALSE;
pads = child->srcpads;
while (pads) {
GstPad *pad = GST_PAD (pads->data);
for (pads = child->srcpads; pads; pads = g_list_next (pads)) {
GstPad *peer;
if (GST_PAD_IS_LINKED (pad)) {
connected_src = TRUE;
break;
peer = gst_pad_get_peer (GST_PAD_CAST (pads->data));
if (peer) {
GstElement *parent;
parent = gst_pad_get_parent (peer);
if (parent) {
GstObject *grandparent;
grandparent = gst_object_get_parent (GST_OBJECT_CAST (parent));
if (grandparent == GST_OBJECT_CAST (bin)) {
connected_src = TRUE;
}
if (grandparent) {
gst_object_unref (GST_OBJECT_CAST (grandparent));
}
gst_object_unref (GST_OBJECT_CAST (parent));
}
gst_object_unref (GST_OBJECT_CAST (peer));
if (connected_src) {
break;
}
}
pads = g_list_next (pads);
}
if (connected_src) {
@ -598,7 +616,7 @@ bin_element_is_sink (GstElement * child, GstBin * bin)
GST_OBJECT_NAME (child));
} else {
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
"adding child %s as sink since it has unlinked source pads",
"adding child %s as sink since it has unlinked source pads in this bin",
GST_OBJECT_NAME (child));
ret = 0;
}
@ -640,8 +658,8 @@ gst_bin_iterate_sinks (GstBin * bin)
return result;
}
/* this functions loops over all children, as soon as one is
* still performing the state change, FALSE is returned.
/* this functions loops over all children, as soon as one does
* not return SUCCESS, we return that value.
*
* MT safe
*/
@ -718,7 +736,17 @@ done:
return ret;
}
/* this function is called with the STATE_LOCK held.
/* this function is called with the STATE_LOCK held. It works
* as follows:
*
* 1) put all sink elements on the queue.
* 2) change state of elements in queue, put linked elements to queue.
* 3) while queue not empty goto 2)
*
* This will effectively change the state of all elements in the bin
* from the sinks to the sources. We have to change the states this
* way so that when a source element pushes data, the downstream element
* is in the right state to receive the data.
*
* MT safe.
*/
@ -735,6 +763,7 @@ gst_bin_change_state (GstElement * element)
bin = GST_BIN (element);
/* we don't need to take the STATE_LOCK, it is already taken */
old_state = GST_STATE (element);
pending = GST_STATE_PENDING (element);
@ -791,7 +820,7 @@ restart:
GST_LOCK (qelement);
pads = qelement->sinkpads;
while (pads) {
GstPad *pad = GST_PAD (pads->data);
GstPad *pad = GST_PAD_CAST (pads->data);
GstPad *peer;
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
@ -799,20 +828,32 @@ restart:
peer = gst_pad_get_peer (pad);
if (peer) {
GstElement *peer_elem;
GstObject *peer_elem;
/* FIXME does not work for bins etc */
peer_elem = GST_ELEMENT (gst_object_get_parent (GST_OBJECT (peer)));
peer_elem = gst_object_get_parent (GST_OBJECT_CAST (peer));
if (peer_elem) {
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
"adding element %s to queue", GST_ELEMENT_NAME (peer_elem));
GstObject *parent;
/* was reffed before pushing on the queue by the
* gst_object_get_parent() call we used to get the element. */
g_queue_push_tail (elem_queue, peer_elem);
/* see if this element is in the bin we are currently handling */
parent = gst_object_get_parent (GST_OBJECT_CAST (peer_elem));
if (parent && parent == GST_OBJECT_CAST (bin)) {
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
"adding element %s to queue", GST_ELEMENT_NAME (peer_elem));
/* was reffed before pushing on the queue by the
* gst_object_get_parent() call we used to get the element. */
g_queue_push_tail (elem_queue, peer_elem);
} else {
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
"not adding element %s to queue, it is in another bin",
GST_ELEMENT_NAME (peer_elem));
}
if (parent) {
gst_object_unref (GST_OBJECT_CAST (parent));
}
}
gst_object_unref (GST_OBJECT (peer));
gst_object_unref (GST_OBJECT_CAST (peer));
} else {
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, element,
"pad %s:%s does not have a peer", GST_DEBUG_PAD_NAME (pad));

View file

@ -125,7 +125,10 @@ gst_bus_dispose (GObject * object)
close (bus->control_socket[0]);
close (bus->control_socket[1]);
g_async_queue_unref (bus->queue);
if (bus->queue) {
g_async_queue_unref (bus->queue);
bus->queue = NULL;
}
G_OBJECT_CLASS (parent_class)->dispose (object);
}
@ -160,6 +163,16 @@ gst_bus_get_property (GObject * object, guint prop_id,
}
}
GstBus *
gst_bus_new (void)
{
GstBus *result;
result = g_object_new (gst_bus_get_type (), NULL);
return result;
}
/**
* gst_bus_post:
* @bus: a #GstBus to post on
@ -167,20 +180,29 @@ gst_bus_get_property (GObject * object, guint prop_id,
*
* Post a message on the given bus.
*
* Returns: the new #GstBuffer.
* Returns: TRUE if the message could be posted.
*
* MT safe.
*/
gboolean
gst_bus_post (GstBus * bus, GstMessage * message)
{
gchar c;
GstBusSyncReply reply = GST_BUS_PASS;
GstBusSyncHandler handler;
gpointer handler_data;
g_return_val_if_fail (GST_IS_BUS (bus), FALSE);
g_return_val_if_fail (GST_IS_MESSAGE (message), FALSE);
GST_LOCK (bus);
handler = bus->sync_handler;
handler_data = bus->sync_handler_data;
GST_UNLOCK (bus);
/* first call the sync handler if it is installed */
if (bus->sync_handler) {
reply = bus->sync_handler (bus, message, bus->sync_handler_data);
if (handler) {
reply = handler (bus, message, handler_data);
}
/* now see what we should do with the message */
@ -236,6 +258,8 @@ gst_bus_post (GstBus * bus, GstMessage * message)
* handled.
*
* Returns: TRUE if there are messages on the bus to be handled.
*
* MT safe.
*/
gboolean
gst_bus_have_pending (GstBus * bus)
@ -257,6 +281,8 @@ gst_bus_have_pending (GstBus * bus)
*
* Returns: The #GstMessage that is on the bus or NULL when there are no
* messages available.
*
* MT safe.
*/
GstMessage *
gst_bus_pop (GstBus * bus)
@ -287,8 +313,10 @@ gst_bus_set_sync_handler (GstBus * bus, GstBusSyncHandler func, gpointer data)
{
g_return_if_fail (GST_IS_BUS (bus));
GST_LOCK (bus);
bus->sync_handler = func;
bus->sync_handler_data = data;
GST_UNLOCK (bus);
}
/**
@ -306,6 +334,8 @@ gst_bus_create_watch (GstBus * bus)
g_return_val_if_fail (GST_IS_BUS (bus), NULL);
/* FIXME, we need to ref the bus and unref it when the source
* is destroyed */
source = g_io_create_watch (bus->io_channel, G_IO_IN);
return source;
@ -342,6 +372,7 @@ bus_destroy (GstBusWatch * watch)
if (watch->notify) {
watch->notify (watch->user_data);
}
gst_object_unref (GST_OBJECT_CAST (watch->bus));
g_free (watch);
}
@ -352,6 +383,8 @@ bus_destroy (GstBusWatch * watch)
* Adds the bus to the mainloop with the given priority.
*
* Returns: The event source id.
*
* MT safe.
*/
guint
gst_bus_add_watch_full (GstBus * bus, gint priority,
@ -364,6 +397,7 @@ gst_bus_add_watch_full (GstBus * bus, gint priority,
watch = g_new (GstBusWatch, 1);
gst_object_ref (GST_OBJECT_CAST (bus));
watch->source = gst_bus_create_watch (bus);
watch->bus = bus;
watch->priority = priority;
@ -390,6 +424,8 @@ gst_bus_add_watch_full (GstBus * bus, gint priority,
* Adds the bus to the mainloop with the default priority.
*
* Returns: The event source id.
*
* MT safe.
*/
guint
gst_bus_add_watch (GstBus * bus, GstBusHandler handler, gpointer user_data)

View file

@ -73,6 +73,8 @@ struct _GstBusClass
GType gst_bus_get_type (void);
GstBus* gst_bus_new (void);
gboolean gst_bus_post (GstBus * bus, GstMessage * message);
gboolean gst_bus_have_pending (GstBus * bus);

View file

@ -490,6 +490,8 @@ gst_clock_set_resolution (GstClock * clock, guint64 resolution)
* Get the accuracy of the clock.
*
* Returns: the resolution of the clock in microseconds.
*
* MT safe.
*/
guint64
gst_clock_get_resolution (GstClock * clock)

View file

@ -28,6 +28,7 @@
#include "gstcpu.h"
#include "gstinfo.h"
static GStaticMutex _cpu_mutex = G_STATIC_MUTEX_INIT;
static guint32 _gst_cpu_flags = 0;
#if defined(HAVE_CPU_I386) && defined(__GNUC__)
@ -89,7 +90,9 @@ _gst_cpu_initialize_i386 (gulong * flags, GString * featurelist)
{
gboolean AMD;
gulong eax = 0, ebx = 0, ecx = 0, edx = 0;
gboolean res = FALSE;
g_static_mutex_lock (&_cpu_mutex);
gst_cpuid_i386 (0, &eax, &ebx, &ecx, &edx);
AMD = (ebx == 0x68747541) && (ecx == 0x444d4163) && (edx == 0x69746e65);
@ -124,13 +127,21 @@ _gst_cpu_initialize_i386 (gulong * flags, GString * featurelist)
}
*flags = eax;
if (_gst_cpu_flags)
return TRUE;
return FALSE;
res = TRUE;
g_static_mutex_unlock (&_cpu_mutex);
return res;
}
#endif
GstCPUFlags
gst_cpu_get_flags (void)
{
return _gst_cpu_flags;
GstCPUFlags res;
g_static_mutex_lock (&_cpu_mutex);
res = _gst_cpu_flags;
g_static_mutex_unlock (&_cpu_mutex);
return res;
}

View file

@ -99,6 +99,8 @@ gst_data_dispose (GstData * data)
* Returns: a copy of the data or NULL if the data cannot be copied.
* The refcount of the original buffer is not changed so you should unref it
* when you don't need it anymore.
*
* MT safe.
*/
GstData *
gst_data_copy (const GstData * data)
@ -119,6 +121,8 @@ gst_data_copy (const GstData * data)
*
* Returns: FALSE if the given #GstData is potentially shared and needs to
* be copied before it can be modified safely.
*
* MT safe.
*/
gboolean
gst_data_is_writable (GstData * data)
@ -129,12 +133,12 @@ gst_data_is_writable (GstData * data)
refcount = gst_atomic_int_read (&data->refcount);
if (refcount > 1)
return FALSE;
if (GST_DATA_FLAG_IS_SET (data, GST_DATA_READONLY))
return FALSE;
/* if we have the only ref and the data is not readonly, we can
* safely write */
if (refcount == 1 && !GST_DATA_FLAG_IS_SET (data, GST_DATA_READONLY))
return TRUE;
return TRUE;
return FALSE;
}
/**
@ -150,6 +154,8 @@ gst_data_is_writable (GstData * data)
*
* The refcount of the passed @data is decreased when a copy is made, so
* you are not supposed to use it anymore after a call to this function.
*
* MT safe.
*/
GstData *
gst_data_copy_on_write (GstData * data)
@ -160,6 +166,8 @@ gst_data_copy_on_write (GstData * data)
refcount = gst_atomic_int_read (&data->refcount);
/* if we have the only ref and the data is not readonly, we can
* safely write, so we return the input data */
if (refcount == 1 && !GST_DATA_FLAG_IS_SET (data, GST_DATA_READONLY))
return GST_DATA (data);
@ -180,6 +188,8 @@ gst_data_copy_on_write (GstData * data)
* Increments the reference count of this data.
*
* Returns: the data
*
* MT safe.
*/
GstData *
gst_data_ref (GstData * data)
@ -203,6 +213,8 @@ gst_data_ref (GstData * data)
* Increments the reference count of this data by the given number.
*
* Returns: the data
*
* MT safe.
*/
GstData *
gst_data_ref_by_count (GstData * data, gint count)
@ -230,6 +242,8 @@ gst_data_ref_by_count (GstData * data, gint count)
* the pipeline takes ownership of the
* data. When the data has been consumed by some element, it must unref() it.
* Applications usually don't need to unref() @data.
*
* MT safe.
*/
void
gst_data_unref (GstData * data)

View file

@ -64,6 +64,7 @@ static void gst_element_base_class_init (gpointer g_class);
static void gst_element_base_class_finalize (gpointer g_class);
static void gst_element_dispose (GObject * object);
static void gst_element_finalize (GObject * object);
static GstElementStateReturn gst_element_change_state (GstElement * element);
static GstElementStateReturn gst_element_get_state_func (GstElement * element,
@ -137,6 +138,7 @@ gst_element_class_init (GstElementClass * klass)
NULL, gst_marshal_VOID__VOID, G_TYPE_NONE, 0);
gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_element_dispose);
gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_element_finalize);
#ifndef GST_DISABLE_LOADSAVE
gstobject_class->save_thyself = GST_DEBUG_FUNCPTR (gst_element_save_thyself);
@ -457,6 +459,8 @@ gst_element_add_pad (GstElement * element, GstPad * pad)
GST_OBJECT_CAST (element))))
goto had_parent;
g_free (pad_name);
/* add it to the list */
switch (gst_pad_get_direction (pad)) {
case GST_PAD_SRC:
@ -486,10 +490,9 @@ gst_element_add_pad (GstElement * element, GstPad * pad)
/* emit the NEW_PAD signal */
g_signal_emit (G_OBJECT (element), gst_element_signals[NEW_PAD], 0, pad);
g_free (pad_name);
return TRUE;
/* ERROR cases */
name_exists:
{
g_critical ("Padname %s is not unique in element %s, not adding",
@ -575,6 +578,8 @@ gst_element_remove_pad (GstElement * element, GstPad * pad)
goto not_our_pad;
GST_UNLOCK (pad);
g_free (pad_name);
/* FIXME, is this redundant with pad disposal? */
if (GST_IS_REAL_PAD (pad)) {
GstPad *peer = gst_pad_get_peer (pad);
@ -619,12 +624,11 @@ gst_element_remove_pad (GstElement * element, GstPad * pad)
gst_object_unparent (GST_OBJECT (pad));
g_free (pad_name);
return TRUE;
not_our_pad:
{
/* FIXME, locking order? */
GST_LOCK (element);
g_critical ("Padname %s:%s does not belong to element %s when removing",
GST_ELEMENT_NAME (GST_PAD_PARENT (pad)), GST_PAD_NAME (pad),
@ -694,8 +698,8 @@ gst_element_get_static_pad (GstElement * element, const gchar * name)
find =
g_list_find_custom (element->pads, name, (GCompareFunc) pad_compare_name);
if (find) {
result = GST_PAD (find->data);
gst_object_ref (GST_OBJECT (result));
result = GST_PAD_CAST (find->data);
gst_object_ref (GST_OBJECT_CAST (result));
}
if (result == NULL) {
@ -1476,8 +1480,7 @@ gst_element_is_locked_state (GstElement * element)
g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
GST_LOCK (element);
/* be careful with the flag tests */
result = !!GST_FLAG_IS_SET (element, GST_ELEMENT_LOCKED_STATE);
result = GST_FLAG_IS_SET (element, GST_ELEMENT_LOCKED_STATE);
GST_UNLOCK (element);
return result;
@ -1569,15 +1572,15 @@ gst_element_get_state_func (GstElement * element,
g_return_val_if_fail (GST_IS_ELEMENT (element), FALSE);
GST_STATE_LOCK (element);
/* we got an error, report immediatly */
if (GST_STATE_ERROR (element))
goto done;
old_pending = GST_STATE_PENDING (element);
if (old_pending != GST_STATE_VOID_PENDING) {
/* we have a pending state change, wait for it to complete */
if (!GST_STATE_TIMED_WAIT (element, timeout)) {
/* timeout triggered */
if (state)
*state = GST_STATE (element);
if (pending)
*pending = GST_STATE_PENDING (element);
ret = GST_STATE_ASYNC;
} else {
/* could be success or failure */
@ -1588,15 +1591,17 @@ gst_element_get_state_func (GstElement * element,
}
}
}
/* if nothing is pending anymore we can return TRUE and
* set the values of the current and pending state */
/* if nothing is pending anymore we can return SUCCESS */
if (GST_STATE_PENDING (element) == GST_STATE_VOID_PENDING) {
if (state)
*state = GST_STATE (element);
if (pending)
*pending = GST_STATE_VOID_PENDING;
ret = GST_STATE_SUCCESS;
}
done:
if (state)
*state = GST_STATE (element);
if (pending)
*pending = GST_STATE_PENDING (element);
GST_STATE_UNLOCK (element);
return ret;
@ -1672,6 +1677,7 @@ gst_element_abort_state (GstElement * element)
"aborting state from %s to %s", gst_element_state_get_name (old_state),
gst_element_state_get_name (pending));
/* flag error */
GST_STATE_ERROR (element) = TRUE;
GST_STATE_BROADCAST (element);
@ -1734,11 +1740,18 @@ gst_element_set_state (GstElement * element, GstElementState state)
GstElementState current;
GstElementStateReturn return_val = GST_STATE_SUCCESS;
oclass = GST_ELEMENT_GET_CLASS (element);
/* get the element state lock */
GST_STATE_LOCK (element);
#if 0
/* a state change is pending and we are not in error, the element is busy
* with a state change and we cannot proceed.
* FIXME, does not work for a bin.*/
if (G_UNLIKELY (GST_STATE_PENDING (element) != GST_STATE_VOID_PENDING &&
!GST_STATE_ERROR (element)))
goto was_busy;
#endif
/* clear the error flag */
GST_STATE_ERROR (element) = FALSE;
@ -1748,6 +1761,8 @@ gst_element_set_state (GstElement * element, GstElementState state)
GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "setting state from %s to %s",
gst_element_state_get_name (current), gst_element_state_get_name (state));
oclass = GST_ELEMENT_GET_CLASS (element);
/* We always perform at least one state change, even if the
* current state is equal to the required state. This is needed
* for bins that sync their children. */
@ -1798,8 +1813,7 @@ gst_element_set_state (GstElement * element, GstElementState state)
GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "commited state");
break;
default:
/* somebody added a GST_STATE_ and forgot to do stuff here ! */
g_assert_not_reached ();
goto invalid_return;
}
/* get the current state of the element and see if we need to do more
* state changes */
@ -1813,15 +1827,35 @@ exit:
GST_CAT_INFO_OBJECT (GST_CAT_STATES, element, "exit state change");
return return_val;
/* ERROR */
#if 0
was_busy:
{
GST_STATE_UNLOCK (element);
GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
"was busy with a state change");
return GST_STATE_BUSY;
}
#endif
invalid_return:
{
GST_STATE_UNLOCK (element);
/* somebody added a GST_STATE_ and forgot to do stuff here ! */
g_critical ("unkown return value from a state change function");
return GST_STATE_FAILURE;
}
}
/* is called with STATE_LOCK
*
* This function activates the pads of a given element.
*
* TODO: activates pads from src to sinks?
*
* */
* TODO: activate pads from src to sinks?
* move pad activate logic to GstPad because we also need this
* when pads are added to elements?
*/
static gboolean
gst_element_pads_activate (GstElement * element, gboolean active)
{
@ -1950,16 +1984,17 @@ gst_element_change_state (GstElement * element)
GST_LOCK (element);
if (GST_ELEMENT_MANAGER (element)) {
element->base_time =
GST_ELEMENT (GST_ELEMENT_MANAGER (element))->base_time;
GST_ELEMENT_CAST (GST_ELEMENT_MANAGER (element))->base_time;
}
GST_UNLOCK (element);
break;
case GST_STATE_PLAYING_TO_PAUSED:
break;
case GST_STATE_PAUSED_TO_READY:
element->base_time = 0;
if (!gst_element_pads_activate (element, FALSE)) {
result = GST_STATE_FAILURE;
} else {
element->base_time = 0;
}
break;
case GST_STATE_READY_TO_NULL:
@ -2010,25 +2045,38 @@ gst_element_dispose (GObject * object)
while (element->pads) {
gst_element_remove_pad (element, GST_PAD (element->pads->data));
}
g_assert (element->pads == 0);
if (G_UNLIKELY (element->pads != 0)) {
g_critical ("could not remove pads from element %s",
GST_STR_NULL (GST_OBJECT_NAME (object)));
}
GST_LOCK (element);
gst_object_replace ((GstObject **) & element->manager, NULL);
gst_object_replace ((GstObject **) & element->clock, NULL);
GST_UNLOCK (element);
GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "dispose parent");
G_OBJECT_CLASS (parent_class)->dispose (object);
}
static void
gst_element_finalize (GObject * object)
{
GstElement *element = GST_ELEMENT (object);
GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "finalize");
GST_STATE_LOCK (element);
if (element->state_cond)
g_cond_free (element->state_cond);
element->state_cond = NULL;
GST_STATE_UNLOCK (element);
g_mutex_free (element->state_lock);
GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "dispose parent");
GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "finalize parent");
G_OBJECT_CLASS (parent_class)->dispose (object);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
#ifndef GST_DISABLE_LOADSAVE
@ -2349,35 +2397,3 @@ gst_element_get_scheduler (GstElement * element)
return result;
}
/**
* gst_element_create_task:
* @element: a #GstElement to create the task for.
* @func: the taskfunction to run
* @data: user data passed to the taskfunction.
*
* Creates a new GstTask. This function uses the current manager of
* the element to instantiate a new task.
*
* Returns: the newly created #GstTask.
*
* MT safe.
*/
GstTask *
gst_element_create_task (GstElement * element, GstTaskFunction func,
gpointer data)
{
GstScheduler *sched;
GstTask *result = NULL;
GST_LOCK (element);
sched = GST_ELEMENT_SCHEDULER (element);
gst_object_ref (GST_OBJECT (sched));
GST_UNLOCK (element);
if (sched) {
result = gst_scheduler_create_task (sched, func, data);
gst_object_unref (GST_OBJECT (sched));
}
return result;
}

View file

@ -35,7 +35,6 @@
#include <gst/gstindex.h>
#include <gst/gstiterator.h>
#include <gst/gstmessage.h>
#include <gst/gsttask.h>
#include <gst/gsttag.h>
G_BEGIN_DECLS typedef struct _GstElementDetails GstElementDetails;
@ -315,8 +314,6 @@ void gst_element_set_bus (GstElement * element, GstBus * bus);
GstBus *gst_element_get_bus (GstElement * element);
void gst_element_set_scheduler (GstElement * element, GstScheduler * scheduler);
GstScheduler *gst_element_get_scheduler (GstElement * element);
GstTask *gst_element_create_task (GstElement * element, GstTaskFunction func,
gpointer data);
/* pad management */
gboolean gst_element_add_pad (GstElement * element, GstPad * pad);

View file

@ -394,7 +394,7 @@ gst_object_replace (GstObject ** oldobj, GstObject * newobj)
#endif
#endif
if (G_UNLIKELY (*oldobj != newobj)) {
if (G_LIKELY (*oldobj != newobj)) {
if (newobj)
gst_object_ref (newobj);
if (*oldobj)

View file

@ -518,6 +518,11 @@ gboolean gst_pad_push_event (GstPad *pad, GstEvent *event);
gboolean gst_pad_send_event (GstPad *pad, GstEvent *event);
gboolean gst_pad_event_default (GstPad *pad, GstEvent *event);
/* pad tasks */
gboolean gst_pad_start_task (GstPad *pad);
gboolean gst_pad_pause_task (GstPad *pad);
gboolean gst_pad_stop_task (GstPad *pad);
/* convert/query/format functions */
void gst_pad_set_formats_function (GstPad *pad,
GstPadFormatsFunction formats);

View file

@ -168,13 +168,13 @@ is_eos (GstPipeline * pipeline)
GstElement *element = GST_ELEMENT (data);
GList *eosed;
GstElementState state, pending;
gboolean complete;
GstElementStateReturn complete;
gchar *name;
complete = gst_element_get_state (element, &state, &pending, NULL);
name = gst_element_get_name (element);
if (!complete) {
if (complete == GST_STATE_ASYNC) {
GST_DEBUG ("element %s still performing state change", name);
result = FALSE;
done = TRUE;
@ -332,9 +332,8 @@ gst_pipeline_change_state (GstElement * element)
/* we wait for async state changes ourselves */
if (result == GST_STATE_ASYNC) {
GST_STATE_UNLOCK (pipeline);
gst_element_get_state (element, NULL, NULL, NULL);
result = gst_element_get_state (element, NULL, NULL, NULL);
GST_STATE_LOCK (pipeline);
result = GST_STATE_SUCCESS;
}
return result;

View file

@ -114,7 +114,7 @@ gst_plugin_error_quark (void)
* plugin description in a list to initialize it when we open the main
* module later on.
* When the main module is known, we can register the plugin right away.
* */
*/
void
_gst_plugin_register_static (GstPluginDesc * desc)
{

View file

@ -22,7 +22,9 @@
#include <glib.h>
G_BEGIN_DECLS typedef struct _GstObject GstObject;
G_BEGIN_DECLS
typedef struct _GstObject GstObject;
typedef struct _GstObjectClass GstObjectClass;
typedef struct _GstPad GstPad;
typedef struct _GstPadClass GstPadClass;
@ -43,18 +45,19 @@ typedef struct _GstMessage GstMessage;
typedef enum
{
GST_STATE_VOID_PENDING = 0,
GST_STATE_NULL = (1 << 0),
GST_STATE_READY = (1 << 1),
GST_STATE_PAUSED = (1 << 2),
GST_STATE_PLAYING = (1 << 3)
GST_STATE_VOID_PENDING = 0,
GST_STATE_NULL = (1 << 0),
GST_STATE_READY = (1 << 1),
GST_STATE_PAUSED = (1 << 2),
GST_STATE_PLAYING = (1 << 3)
} GstElementState;
typedef enum
{
GST_STATE_FAILURE = 0,
GST_STATE_SUCCESS = 1,
GST_STATE_ASYNC = 2
GST_STATE_FAILURE = 0,
GST_STATE_SUCCESS = 1,
GST_STATE_ASYNC = 2,
GST_STATE_BUSY = 3
} GstElementStateReturn;
typedef enum
@ -66,15 +69,14 @@ typedef enum
typedef enum
{
GST_RANK_NONE = 0,
GST_RANK_MARGINAL = 64,
GST_RANK_SECONDARY = 128,
GST_RANK_PRIMARY = 256
GST_RANK_NONE = 0,
GST_RANK_MARGINAL = 64,
GST_RANK_SECONDARY = 128,
GST_RANK_PRIMARY = 256
} GstRank;
#define GST_PADDING 4
#define GST_PADDING_INIT { 0 }
G_END_DECLS
#endif /* __GST_TYPES_H__ */

View file

@ -773,7 +773,7 @@ gst_element_state_get_name (GstElementState state)
return "PAUSED";
break;
default:
return "UNKNOWN!";
return g_strdup_printf ("UNKNOWN!(%d)", state);
#endif
}
return "";

View file

@ -180,6 +180,7 @@ static gboolean gst_filesrc_srcpad_query (GstPad * pad, GstQueryType type,
static gboolean gst_filesrc_activate (GstPad * pad, GstActivateMode mode);
static GstElementStateReturn gst_filesrc_change_state (GstElement * element);
static GstCaps *gst_filesrc_type_find (GstFileSrc * src);
static void gst_filesrc_uri_handler_init (gpointer g_iface,
gpointer iface_data);
@ -854,6 +855,22 @@ gst_filesrc_open_file (GstFileSrc * src)
src->curoffset = 0;
GST_FLAG_SET (src, GST_FILESRC_OPEN);
{
GstCaps *caps;
guint64 offset;
guint length;
offset = src->curoffset;
length = src->block_size;
caps = gst_filesrc_type_find (src);
gst_pad_set_caps (src->srcpad, caps);
src->curoffset = offset;
src->block_size = length;
}
}
return TRUE;
}
@ -1122,6 +1139,89 @@ error:
return FALSE;
}
typedef struct
{
GstFileSrc *src;
guint best_probability;
GstCaps *caps;
GstBuffer *buffer;
}
FileSrcTypeFind;
static guint8 *
filesrc_find_peek (gpointer data, gint64 offset, guint size)
{
FileSrcTypeFind *find;
GstBuffer *buffer;
GstFileSrc *src;
if (size == 0)
return NULL;
find = (FileSrcTypeFind *) data;
src = find->src;
if (offset < 0) {
offset += src->filelen;
}
buffer = NULL;
gst_filesrc_getrange (src->srcpad, offset, size, &buffer);
if (find->buffer) {
gst_buffer_unref (find->buffer);
}
find->buffer = buffer;
return GST_BUFFER_DATA (buffer);
}
static void
filesrc_find_suggest (gpointer data, guint probability, const GstCaps * caps)
{
FileSrcTypeFind *find = (FileSrcTypeFind *) data;
if (probability > find->best_probability) {
gst_caps_replace (&find->caps, gst_caps_copy (caps));
find->best_probability = probability;
}
}
static GstCaps *
gst_filesrc_type_find (GstFileSrc * src)
{
GstTypeFind gst_find;
FileSrcTypeFind find;
GList *walk, *type_list = NULL;
GstCaps *result = NULL;
walk = type_list = gst_type_find_factory_get_list ();
find.src = src;
find.best_probability = 0;
find.caps = NULL;
gst_find.data = &find;
gst_find.peek = filesrc_find_peek;
gst_find.suggest = filesrc_find_suggest;
gst_find.get_length = NULL;
while (walk) {
GstTypeFindFactory *factory = GST_TYPE_FIND_FACTORY (walk->data);
gst_type_find_factory_call_function (factory, &gst_find);
if (find.best_probability >= GST_TYPE_FIND_MAXIMUM)
break;
walk = g_list_next (walk);
}
if (find.best_probability > 0)
result = find.caps;
return result;
}
/*** GSTURIHANDLER INTERFACE *************************************************/
static guint

View file

@ -6,6 +6,10 @@ Makefile.in
.deps
.libs
test1
test2
test3
test4
bin
locked
parent

View file

@ -1,5 +1,5 @@
include ../Rules
tests_pass = locked parent
tests_pass = test1 test2 test3 test4 locked parent
tests_fail =
tests_ignore = bin
tests_ignore =

View file

@ -21,6 +21,8 @@
#include <gst/gst.h>
static GMainLoop *loop;
static gboolean
message_received (GstBus * bus, GstMessage * message, GstPipeline * pipeline)
{
@ -28,7 +30,8 @@ message_received (GstBus * bus, GstMessage * message, GstPipeline * pipeline)
if (message->type == GST_MESSAGE_EOS) {
g_print ("EOS!!\n");
gst_main_quit ();
if (g_main_loop_is_running (loop))
g_main_loop_quit (loop);
}
gst_message_unref (message);
@ -47,8 +50,10 @@ main (gint argc, gchar * argv[])
pipeline = gst_pipeline_new ("pipeline");
bus = GST_PIPELINE (pipeline)->bus;
loop = g_main_loop_new (NULL, FALSE);
bus = gst_element_get_bus (pipeline);
gst_bus_add_watch (bus, (GstBusHandler) message_received, pipeline);
gst_object_unref (GST_OBJECT (bus));
fakesrc1 = gst_element_factory_make ("fakesrc", "fakesrc1");
g_object_set (G_OBJECT (fakesrc1), "num_buffers", 5, NULL);
@ -77,7 +82,7 @@ main (gint argc, gchar * argv[])
g_print ("play..\n");
gst_element_set_state (pipeline, GST_STATE_PLAYING);
gst_main ();
g_main_loop_run (loop);
g_object_set (G_OBJECT (fakesrc1), "num_buffers", 5, NULL);
@ -89,7 +94,7 @@ main (gint argc, gchar * argv[])
g_print ("play..\n");
gst_element_set_state (pipeline, GST_STATE_PLAYING);
gst_main ();
g_main_loop_run (loop);
gst_element_set_state (pipeline, GST_STATE_NULL);

View file

@ -67,7 +67,7 @@ main (gint argc, gchar * argv[])
gst_bin_add (GST_BIN (pipeline), bin2);
g_signal_connect (G_OBJECT (pipeline), "deep_notify",
G_CALLBACK (gst_element_default_deep_notify), NULL);
G_CALLBACK (gst_object_default_deep_notify), NULL);
/* setting pipeline to READY should bring in all children to READY */
gst_element_set_state (pipeline, GST_STATE_READY);
@ -77,31 +77,35 @@ main (gint argc, gchar * argv[])
g_assert (GST_STATE (identity) == GST_STATE_READY);
g_assert (GST_STATE (fakesink) == GST_STATE_READY);
/* setting fakesink to PAUSED should set pipeline and bin2 to PAUSED */
/* setting fakesink to PAUSED should not affect pipeline and bin2 */
gst_element_set_state (fakesink, GST_STATE_PAUSED);
g_assert (GST_STATE (bin1) == GST_STATE_READY);
g_assert (GST_STATE (bin2) == GST_STATE_PAUSED);
g_assert (GST_STATE (bin2) == GST_STATE_READY);
g_assert (GST_STATE (fakesrc) == GST_STATE_READY);
g_assert (GST_STATE (identity) == GST_STATE_READY);
g_assert (GST_STATE (fakesink) == GST_STATE_PAUSED);
g_assert (GST_STATE (fakesink) == GST_STATE_READY);
/* setting fakesrc to PAUSED should set bin1 and fakesrc to PAUSED */
/* setting fakesrc to PAUSED should not affect bin1 */
gst_element_set_state (fakesrc, GST_STATE_PAUSED);
g_assert (GST_STATE (bin1) == GST_STATE_PAUSED);
g_assert (GST_STATE (bin2) == GST_STATE_PAUSED);
g_assert (GST_STATE (bin1) == GST_STATE_READY);
g_assert (GST_STATE (bin2) == GST_STATE_READY);
g_assert (GST_STATE (fakesrc) == GST_STATE_PAUSED);
g_assert (GST_STATE (identity) == GST_STATE_READY);
g_assert (GST_STATE (fakesink) == GST_STATE_PAUSED);
g_assert (GST_STATE (fakesink) == GST_STATE_READY);
/* setting bin1 to PAUSED, even though it is already, should set
* identity to PAUSED as well */
gst_element_set_state (bin1, GST_STATE_PAUSED);
gst_element_get_state (bin2, NULL, NULL, NULL);
g_assert (GST_STATE (bin1) == GST_STATE_PAUSED);
g_assert (GST_STATE (bin2) == GST_STATE_PAUSED);
g_assert (GST_STATE (bin2) == GST_STATE_READY);
g_assert (GST_STATE (fakesrc) == GST_STATE_PAUSED);
g_assert (GST_STATE (identity) == GST_STATE_PAUSED);
g_assert (GST_STATE (fakesink) == GST_STATE_PAUSED);
gst_element_set_state (pipeline, GST_STATE_PLAYING);
g_usleep (1000000);
g_print ("passed.\n");
return 0;
}

View file

@ -0,0 +1,208 @@
/* GStreamer
* Copyright (C) <2005> Wim Taymans <wim@fluendo.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "unistd.h"
#include <gst/gst.h>
static GMainLoop *loop;
static gboolean
message_received (GstBus * bus, GstMessage * message, gpointer ignored)
{
g_print ("message %p\n", message);
if (message->type == GST_MESSAGE_EOS) {
g_print ("EOS!!\n");
if (g_main_loop_is_running (loop))
g_main_loop_quit (loop);
}
gst_message_unref (message);
return TRUE;
}
static gboolean
set_state (GstElement * element, GstElementState state,
GstElementStateReturn expected)
{
GstElementStateReturn ret;
gboolean res;
g_print ("setting state to %s, expecting %d...",
gst_element_state_get_name (state), expected);
ret = gst_element_set_state (element, state);
res = (ret == expected);
g_print ("%s\n", res ? "OK" : "failed");
return res;
}
static gboolean
get_state (GstElement * element, GstElementState exp_state,
GstElementState exp_pending, GTimeVal * timeval,
GstElementStateReturn expected)
{
GstElementStateReturn ret;
gboolean res;
GstElementState state, pending;
g_print ("getting state: expecting %s, %s, %d...",
gst_element_state_get_name (exp_state),
gst_element_state_get_name (exp_pending), expected);
ret = gst_element_get_state (element, &state, &pending, timeval);
res = (ret == expected);
res &= (state == exp_state);
res &= (pending == exp_pending);
if (res) {
g_print ("OK\n");
} else {
g_print ("failed, got %s, %s, %d\n",
gst_element_state_get_name (state),
gst_element_state_get_name (pending), ret);
}
return res;
}
static gboolean
commit_callback (GstClock * clock, GstClockTime time,
GstClockID id, GstElement * element)
{
g_print ("commiting state change..");
gst_element_commit_state (element);
return FALSE;
}
static gboolean
abort_callback (GstClock * clock, GstClockTime time,
GstClockID id, GstElement * element)
{
g_print ("aborting state change..");
gst_element_abort_state (element);
return FALSE;
}
gint
main (gint argc, gchar * argv[])
{
GstElement *fakesink;
GstBus *bus;
GTimeVal timeval;
GstClock *clock;
GstClockID id;
GstClockTime base;
GstClockReturn result;
gst_init (&argc, &argv);
loop = g_main_loop_new (NULL, FALSE);
bus = gst_bus_new ();
gst_bus_add_watch (bus, (GstBusHandler) message_received, NULL);
clock = gst_system_clock_obtain ();
g_assert (clock != NULL);
fakesink = gst_element_factory_make ("fakesink", "fakesink");
g_assert (fakesink);
gst_element_set_bus (fakesink, bus);
g_assert (set_state (fakesink, GST_STATE_READY, GST_STATE_SUCCESS));
g_assert (get_state (fakesink, GST_STATE_READY, GST_STATE_VOID_PENDING, NULL,
GST_STATE_SUCCESS));
g_assert (set_state (fakesink, GST_STATE_PAUSED, GST_STATE_ASYNC));
g_get_current_time (&timeval);
g_time_val_add (&timeval, G_USEC_PER_SEC * 1);
g_assert (get_state (fakesink, GST_STATE_READY, GST_STATE_PAUSED, &timeval,
GST_STATE_ASYNC));
g_assert (get_state (fakesink, GST_STATE_READY, GST_STATE_PAUSED, &timeval,
GST_STATE_ASYNC));
g_assert (set_state (fakesink, GST_STATE_READY, GST_STATE_SUCCESS));
g_assert (get_state (fakesink, GST_STATE_READY, GST_STATE_VOID_PENDING, NULL,
GST_STATE_SUCCESS));
g_assert (set_state (fakesink, GST_STATE_PAUSED, GST_STATE_ASYNC));
g_assert (get_state (fakesink, GST_STATE_READY, GST_STATE_PAUSED, &timeval,
GST_STATE_ASYNC));
g_print ("aborting state change..\n");
gst_element_abort_state (fakesink);
g_assert (get_state (fakesink, GST_STATE_READY, GST_STATE_PAUSED, &timeval,
GST_STATE_FAILURE));
g_assert (set_state (fakesink, GST_STATE_PAUSED, GST_STATE_ASYNC));
g_assert (get_state (fakesink, GST_STATE_READY, GST_STATE_PAUSED, &timeval,
GST_STATE_ASYNC));
g_print ("commiting state change..\n");
gst_element_commit_state (fakesink);
g_assert (get_state (fakesink, GST_STATE_PAUSED, GST_STATE_VOID_PENDING,
&timeval, GST_STATE_SUCCESS));
g_assert (set_state (fakesink, GST_STATE_READY, GST_STATE_SUCCESS));
g_assert (get_state (fakesink, GST_STATE_READY, GST_STATE_VOID_PENDING,
&timeval, GST_STATE_SUCCESS));
g_assert (set_state (fakesink, GST_STATE_PAUSED, GST_STATE_ASYNC));
base = gst_clock_get_time (clock);
id = gst_clock_new_single_shot_id (clock, base + 1 * GST_SECOND);
g_print ("waiting one second async id %p to abort state\n", id);
result =
gst_clock_id_wait_async (id, (GstClockCallback) abort_callback, fakesink);
gst_clock_id_unref (id);
g_assert (result == GST_CLOCK_OK);
g_assert (get_state (fakesink, GST_STATE_READY, GST_STATE_PAUSED, NULL,
GST_STATE_FAILURE));
g_assert (get_state (fakesink, GST_STATE_READY, GST_STATE_PAUSED, NULL,
GST_STATE_FAILURE));
g_assert (set_state (fakesink, GST_STATE_PAUSED, GST_STATE_ASYNC));
id = gst_clock_new_single_shot_id (clock, base + 1 * GST_SECOND);
g_print ("waiting one second async id %p to commit state\n", id);
result =
gst_clock_id_wait_async (id, (GstClockCallback) commit_callback,
fakesink);
gst_clock_id_unref (id);
g_assert (result == GST_CLOCK_OK);
g_assert (get_state (fakesink, GST_STATE_PAUSED, GST_STATE_VOID_PENDING, NULL,
GST_STATE_SUCCESS));
g_assert (get_state (fakesink, GST_STATE_PAUSED, GST_STATE_VOID_PENDING, NULL,
GST_STATE_SUCCESS));
g_print ("passed..\n");
gst_object_unref (GST_OBJECT (fakesink));
return 0;
}

View file

@ -0,0 +1,131 @@
/* GStreamer
* Copyright (C) <2005> Wim Taymans <wim@fluendo.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "unistd.h"
#include <gst/gst.h>
static GMainLoop *loop;
static gboolean
message_received (GstBus * bus, GstMessage * message, gpointer ignored)
{
g_print ("message %p\n", message);
if (message->type == GST_MESSAGE_EOS) {
g_print ("EOS!!\n");
if (g_main_loop_is_running (loop))
g_main_loop_quit (loop);
}
gst_message_unref (message);
return TRUE;
}
static gboolean
set_state (GstElement * element, GstElementState state,
GstElementStateReturn expected)
{
GstElementStateReturn ret;
gboolean res;
g_print ("setting state to %s, expecting %d...",
gst_element_state_get_name (state), expected);
ret = gst_element_set_state (element, state);
res = (ret == expected);
if (res) {
g_print ("OK\n");
} else {
g_print ("failed, got %d\n", ret);
}
return res;
}
static gboolean
get_state (GstElement * element, GstElementState exp_state,
GstElementState exp_pending, GTimeVal * timeval,
GstElementStateReturn expected)
{
GstElementStateReturn ret;
gboolean res;
GstElementState state, pending;
g_print ("getting state: expecting %s, %s, %d...",
gst_element_state_get_name (exp_state),
gst_element_state_get_name (exp_pending), expected);
ret = gst_element_get_state (element, &state, &pending, timeval);
res = (ret == expected);
res &= (state == exp_state);
res &= (pending == exp_pending);
if (res) {
g_print ("OK\n");
} else {
g_print ("failed, got %s, %s, %d\n",
gst_element_state_get_name (state),
gst_element_state_get_name (pending), ret);
}
return res;
}
gint
main (gint argc, gchar * argv[])
{
GstElement *fakesink;
GstBus *bus;
GTimeVal timeval;
GstClock *clock;
gst_init (&argc, &argv);
loop = g_main_loop_new (NULL, FALSE);
bus = gst_bus_new ();
gst_bus_add_watch (bus, (GstBusHandler) message_received, NULL);
clock = gst_system_clock_obtain ();
g_assert (clock != NULL);
fakesink = gst_element_factory_make ("fakesink", "fakesink");
g_assert (fakesink);
gst_element_set_bus (fakesink, bus);
g_assert (set_state (fakesink, GST_STATE_READY, GST_STATE_SUCCESS));
g_assert (get_state (fakesink, GST_STATE_READY, GST_STATE_VOID_PENDING, NULL,
GST_STATE_SUCCESS));
g_assert (set_state (fakesink, GST_STATE_PAUSED, GST_STATE_ASYNC));
g_assert (set_state (fakesink, GST_STATE_PLAYING, GST_STATE_ASYNC));
g_get_current_time (&timeval);
g_time_val_add (&timeval, G_USEC_PER_SEC * 1);
g_assert (get_state (fakesink, GST_STATE_READY, GST_STATE_PAUSED, &timeval,
GST_STATE_ASYNC));
g_print ("passed..\n");
gst_object_unref (GST_OBJECT (fakesink));
return 0;
}

View file

@ -0,0 +1,136 @@
/* GStreamer
* Copyright (C) <2005> Wim Taymans <wim@fluendo.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "unistd.h"
#include <gst/gst.h>
static GMainLoop *loop;
static gboolean
message_received (GstBus * bus, GstMessage * message, gpointer ignored)
{
g_print ("message %p\n", message);
if (message->type == GST_MESSAGE_EOS) {
g_print ("EOS!!\n");
if (g_main_loop_is_running (loop))
g_main_loop_quit (loop);
}
gst_message_unref (message);
return TRUE;
}
static gboolean
set_state (GstElement * element, GstElementState state,
GstElementStateReturn expected)
{
GstElementStateReturn ret;
gboolean res;
g_print ("setting state to %s, expecting %d...",
gst_element_state_get_name (state), expected);
ret = gst_element_set_state (element, state);
res = (ret == expected);
if (res) {
g_print ("OK\n");
} else {
g_print ("failed, got %d\n", ret);
}
return res;
}
static gboolean
get_state (GstElement * element, GstElementState exp_state,
GstElementState exp_pending, GTimeVal * timeval,
GstElementStateReturn expected)
{
GstElementStateReturn ret;
gboolean res;
GstElementState state, pending;
g_print ("getting state: expecting %s, %s, %d...",
gst_element_state_get_name (exp_state),
gst_element_state_get_name (exp_pending), expected);
ret = gst_element_get_state (element, &state, &pending, timeval);
res = (ret == expected);
res &= (state == exp_state);
res &= (pending == exp_pending);
if (res) {
g_print ("OK\n");
} else {
g_print ("failed, got %s, %s, %d\n",
gst_element_state_get_name (state),
gst_element_state_get_name (pending), ret);
}
return res;
}
gint
main (gint argc, gchar * argv[])
{
GstElement *bin;
GstBus *bus;
GstClock *clock;
gst_init (&argc, &argv);
loop = g_main_loop_new (NULL, FALSE);
bus = gst_bus_new ();
gst_bus_add_watch (bus, (GstBusHandler) message_received, NULL);
clock = gst_system_clock_obtain ();
g_assert (clock != NULL);
bin = gst_element_factory_make ("bin", "bin");
g_assert (bin);
gst_element_set_bus (bin, bus);
g_assert (set_state (bin, GST_STATE_READY, GST_STATE_SUCCESS));
g_assert (get_state (bin, GST_STATE_READY, GST_STATE_VOID_PENDING, NULL,
GST_STATE_SUCCESS));
g_assert (set_state (bin, GST_STATE_PAUSED, GST_STATE_SUCCESS));
g_assert (get_state (bin, GST_STATE_PAUSED, GST_STATE_VOID_PENDING, NULL,
GST_STATE_SUCCESS));
g_assert (set_state (bin, GST_STATE_PLAYING, GST_STATE_SUCCESS));
g_assert (get_state (bin, GST_STATE_PLAYING, GST_STATE_VOID_PENDING, NULL,
GST_STATE_SUCCESS));
g_assert (set_state (bin, GST_STATE_PAUSED, GST_STATE_SUCCESS));
g_assert (get_state (bin, GST_STATE_PAUSED, GST_STATE_VOID_PENDING, NULL,
GST_STATE_SUCCESS));
g_assert (set_state (bin, GST_STATE_READY, GST_STATE_SUCCESS));
g_assert (get_state (bin, GST_STATE_READY, GST_STATE_VOID_PENDING, NULL,
GST_STATE_SUCCESS));
g_print ("passed..\n");
gst_object_unref (GST_OBJECT (bin));
return 0;
}

View file

@ -0,0 +1,230 @@
/* GStreamer
* Copyright (C) <2005> Wim Taymans <wim@fluendo.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "unistd.h"
#include <gst/gst.h>
static GMainLoop *loop;
static gboolean
message_received (GstBus * bus, GstMessage * message, gpointer ignored)
{
g_print ("message %p\n", message);
if (message->type == GST_MESSAGE_EOS) {
g_print ("EOS!!\n");
if (g_main_loop_is_running (loop))
g_main_loop_quit (loop);
}
gst_message_unref (message);
return TRUE;
}
static gboolean
set_state (GstElement * element, GstElementState state,
GstElementStateReturn expected)
{
GstElementStateReturn ret;
gboolean res;
g_print ("setting %s state to %s, expecting %d...",
gst_element_get_name (element),
gst_element_state_get_name (state), expected);
ret = gst_element_set_state (element, state);
res = (ret == expected);
g_print ("%s\n", res ? "OK" : "failed");
return res;
}
static gboolean
get_state (GstElement * element, GstElementState exp_state,
GstElementState exp_pending, GTimeVal * timeval,
GstElementStateReturn expected)
{
GstElementStateReturn ret;
gboolean res;
GstElementState state, pending;
g_print ("getting state %s: expecting %s, %s, %d...",
gst_element_get_name (element),
gst_element_state_get_name (exp_state),
gst_element_state_get_name (exp_pending), expected);
ret = gst_element_get_state (element, &state, &pending, timeval);
res = (ret == expected);
res &= (state == exp_state);
res &= (pending == exp_pending);
if (res) {
g_print ("OK\n");
} else {
g_print ("failed, got %s, %s, %d\n",
gst_element_state_get_name (state),
gst_element_state_get_name (pending), ret);
}
return res;
}
static gboolean
commit_callback (GstClock * clock, GstClockTime time,
GstClockID id, GstElement * element)
{
g_print ("commiting state change..");
gst_element_commit_state (element);
return FALSE;
}
static gboolean
abort_callback (GstClock * clock, GstClockTime time,
GstClockID id, GstElement * element)
{
g_print ("aborting state change..");
gst_element_abort_state (element);
return FALSE;
}
gint
main (gint argc, gchar * argv[])
{
GstElement *fakesink, *bin;
GstBus *bus;
GTimeVal timeval;
GstClock *clock;
GstClockID id;
GstClockTime base;
GstClockReturn result;
gst_init (&argc, &argv);
loop = g_main_loop_new (NULL, FALSE);
bus = gst_bus_new ();
gst_bus_add_watch (bus, (GstBusHandler) message_received, NULL);
clock = gst_system_clock_obtain ();
g_assert (clock != NULL);
fakesink = gst_element_factory_make ("fakesink", "fakesink");
g_assert (fakesink);
bin = gst_element_factory_make ("bin", "bin");
g_assert (bin);
gst_bin_add (GST_BIN (bin), fakesink);
gst_element_set_bus (bin, bus);
g_assert (set_state (bin, GST_STATE_READY, GST_STATE_SUCCESS));
g_assert (get_state (bin, GST_STATE_READY, GST_STATE_VOID_PENDING, NULL,
GST_STATE_SUCCESS));
g_assert (get_state (fakesink, GST_STATE_READY, GST_STATE_VOID_PENDING, NULL,
GST_STATE_SUCCESS));
g_assert (set_state (fakesink, GST_STATE_NULL, GST_STATE_SUCCESS));
g_assert (get_state (bin, GST_STATE_READY, GST_STATE_VOID_PENDING, NULL,
GST_STATE_SUCCESS));
g_assert (get_state (fakesink, GST_STATE_NULL, GST_STATE_VOID_PENDING, NULL,
GST_STATE_SUCCESS));
g_assert (set_state (bin, GST_STATE_READY, GST_STATE_SUCCESS));
g_assert (get_state (bin, GST_STATE_READY, GST_STATE_VOID_PENDING, NULL,
GST_STATE_SUCCESS));
g_assert (get_state (fakesink, GST_STATE_READY, GST_STATE_VOID_PENDING, NULL,
GST_STATE_SUCCESS));
g_get_current_time (&timeval);
g_time_val_add (&timeval, G_USEC_PER_SEC / 2);
g_assert (set_state (fakesink, GST_STATE_PAUSED, GST_STATE_ASYNC));
g_assert (get_state (bin, GST_STATE_READY, GST_STATE_VOID_PENDING, &timeval,
GST_STATE_ASYNC));
g_time_val_add (&timeval, G_USEC_PER_SEC / 2);
g_assert (get_state (fakesink, GST_STATE_READY, GST_STATE_PAUSED, &timeval,
GST_STATE_ASYNC));
g_assert (get_state (bin, GST_STATE_READY, GST_STATE_VOID_PENDING, &timeval,
GST_STATE_ASYNC));
g_assert (set_state (fakesink, GST_STATE_READY, GST_STATE_SUCCESS));
g_assert (get_state (bin, GST_STATE_READY, GST_STATE_VOID_PENDING, NULL,
GST_STATE_SUCCESS));
g_assert (get_state (fakesink, GST_STATE_READY, GST_STATE_VOID_PENDING, NULL,
GST_STATE_SUCCESS));
g_assert (set_state (bin, GST_STATE_PAUSED, GST_STATE_ASYNC));
g_time_val_add (&timeval, G_USEC_PER_SEC / 2);
g_assert (get_state (bin, GST_STATE_READY, GST_STATE_PAUSED, &timeval,
GST_STATE_ASYNC));
g_time_val_add (&timeval, G_USEC_PER_SEC / 2);
g_assert (get_state (fakesink, GST_STATE_READY, GST_STATE_PAUSED, &timeval,
GST_STATE_ASYNC));
g_assert (set_state (bin, GST_STATE_READY, GST_STATE_SUCCESS));
g_assert (get_state (bin, GST_STATE_READY, GST_STATE_VOID_PENDING, &timeval,
GST_STATE_SUCCESS));
g_assert (get_state (fakesink, GST_STATE_READY, GST_STATE_VOID_PENDING,
&timeval, GST_STATE_SUCCESS));
g_assert (set_state (bin, GST_STATE_PAUSED, GST_STATE_ASYNC));
g_assert (set_state (fakesink, GST_STATE_READY, GST_STATE_SUCCESS));
g_time_val_add (&timeval, G_USEC_PER_SEC / 2);
g_assert (get_state (bin, GST_STATE_PAUSED, GST_STATE_VOID_PENDING, &timeval,
GST_STATE_SUCCESS));
g_assert (set_state (bin, GST_STATE_READY, GST_STATE_SUCCESS));
g_assert (get_state (bin, GST_STATE_READY, GST_STATE_VOID_PENDING, &timeval,
GST_STATE_SUCCESS));
g_assert (set_state (bin, GST_STATE_PAUSED, GST_STATE_ASYNC));
base = gst_clock_get_time (clock);
id = gst_clock_new_single_shot_id (clock, base + 1 * GST_SECOND);
g_print ("waiting one second async id %p to abort state\n", id);
result =
gst_clock_id_wait_async (id, (GstClockCallback) abort_callback, fakesink);
gst_clock_id_unref (id);
g_assert (result == GST_CLOCK_OK);
g_assert (get_state (bin, GST_STATE_READY, GST_STATE_PAUSED, NULL,
GST_STATE_FAILURE));
g_assert (set_state (bin, GST_STATE_PAUSED, GST_STATE_ASYNC));
base = gst_clock_get_time (clock);
id = gst_clock_new_single_shot_id (clock, base + 1 * GST_SECOND);
g_print ("waiting one second async id %p to commit state\n", id);
result =
gst_clock_id_wait_async (id, (GstClockCallback) commit_callback,
fakesink);
gst_clock_id_unref (id);
g_assert (result == GST_CLOCK_OK);
g_assert (get_state (bin, GST_STATE_PAUSED, GST_STATE_VOID_PENDING, NULL,
GST_STATE_SUCCESS));
g_print ("passed..\n");
gst_object_unref (GST_OBJECT (fakesink));
return 0;
}

View file

@ -6,6 +6,10 @@ Makefile.in
.deps
.libs
test1
test2
test3
test4
bin
locked
parent

View file

@ -1,5 +1,5 @@
include ../Rules
tests_pass = locked parent
tests_pass = test1 test2 test3 test4 locked parent
tests_fail =
tests_ignore = bin
tests_ignore =

View file

@ -21,6 +21,8 @@
#include <gst/gst.h>
static GMainLoop *loop;
static gboolean
message_received (GstBus * bus, GstMessage * message, GstPipeline * pipeline)
{
@ -28,7 +30,8 @@ message_received (GstBus * bus, GstMessage * message, GstPipeline * pipeline)
if (message->type == GST_MESSAGE_EOS) {
g_print ("EOS!!\n");
gst_main_quit ();
if (g_main_loop_is_running (loop))
g_main_loop_quit (loop);
}
gst_message_unref (message);
@ -47,8 +50,10 @@ main (gint argc, gchar * argv[])
pipeline = gst_pipeline_new ("pipeline");
bus = GST_PIPELINE (pipeline)->bus;
loop = g_main_loop_new (NULL, FALSE);
bus = gst_element_get_bus (pipeline);
gst_bus_add_watch (bus, (GstBusHandler) message_received, pipeline);
gst_object_unref (GST_OBJECT (bus));
fakesrc1 = gst_element_factory_make ("fakesrc", "fakesrc1");
g_object_set (G_OBJECT (fakesrc1), "num_buffers", 5, NULL);
@ -77,7 +82,7 @@ main (gint argc, gchar * argv[])
g_print ("play..\n");
gst_element_set_state (pipeline, GST_STATE_PLAYING);
gst_main ();
g_main_loop_run (loop);
g_object_set (G_OBJECT (fakesrc1), "num_buffers", 5, NULL);
@ -89,7 +94,7 @@ main (gint argc, gchar * argv[])
g_print ("play..\n");
gst_element_set_state (pipeline, GST_STATE_PLAYING);
gst_main ();
g_main_loop_run (loop);
gst_element_set_state (pipeline, GST_STATE_NULL);

View file

@ -67,7 +67,7 @@ main (gint argc, gchar * argv[])
gst_bin_add (GST_BIN (pipeline), bin2);
g_signal_connect (G_OBJECT (pipeline), "deep_notify",
G_CALLBACK (gst_element_default_deep_notify), NULL);
G_CALLBACK (gst_object_default_deep_notify), NULL);
/* setting pipeline to READY should bring in all children to READY */
gst_element_set_state (pipeline, GST_STATE_READY);
@ -77,31 +77,35 @@ main (gint argc, gchar * argv[])
g_assert (GST_STATE (identity) == GST_STATE_READY);
g_assert (GST_STATE (fakesink) == GST_STATE_READY);
/* setting fakesink to PAUSED should set pipeline and bin2 to PAUSED */
/* setting fakesink to PAUSED should not affect pipeline and bin2 */
gst_element_set_state (fakesink, GST_STATE_PAUSED);
g_assert (GST_STATE (bin1) == GST_STATE_READY);
g_assert (GST_STATE (bin2) == GST_STATE_PAUSED);
g_assert (GST_STATE (bin2) == GST_STATE_READY);
g_assert (GST_STATE (fakesrc) == GST_STATE_READY);
g_assert (GST_STATE (identity) == GST_STATE_READY);
g_assert (GST_STATE (fakesink) == GST_STATE_PAUSED);
g_assert (GST_STATE (fakesink) == GST_STATE_READY);
/* setting fakesrc to PAUSED should set bin1 and fakesrc to PAUSED */
/* setting fakesrc to PAUSED should not affect bin1 */
gst_element_set_state (fakesrc, GST_STATE_PAUSED);
g_assert (GST_STATE (bin1) == GST_STATE_PAUSED);
g_assert (GST_STATE (bin2) == GST_STATE_PAUSED);
g_assert (GST_STATE (bin1) == GST_STATE_READY);
g_assert (GST_STATE (bin2) == GST_STATE_READY);
g_assert (GST_STATE (fakesrc) == GST_STATE_PAUSED);
g_assert (GST_STATE (identity) == GST_STATE_READY);
g_assert (GST_STATE (fakesink) == GST_STATE_PAUSED);
g_assert (GST_STATE (fakesink) == GST_STATE_READY);
/* setting bin1 to PAUSED, even though it is already, should set
* identity to PAUSED as well */
gst_element_set_state (bin1, GST_STATE_PAUSED);
gst_element_get_state (bin2, NULL, NULL, NULL);
g_assert (GST_STATE (bin1) == GST_STATE_PAUSED);
g_assert (GST_STATE (bin2) == GST_STATE_PAUSED);
g_assert (GST_STATE (bin2) == GST_STATE_READY);
g_assert (GST_STATE (fakesrc) == GST_STATE_PAUSED);
g_assert (GST_STATE (identity) == GST_STATE_PAUSED);
g_assert (GST_STATE (fakesink) == GST_STATE_PAUSED);
gst_element_set_state (pipeline, GST_STATE_PLAYING);
g_usleep (1000000);
g_print ("passed.\n");
return 0;
}

208
testsuite/states/test1.c Normal file
View file

@ -0,0 +1,208 @@
/* GStreamer
* Copyright (C) <2005> Wim Taymans <wim@fluendo.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "unistd.h"
#include <gst/gst.h>
static GMainLoop *loop;
static gboolean
message_received (GstBus * bus, GstMessage * message, gpointer ignored)
{
g_print ("message %p\n", message);
if (message->type == GST_MESSAGE_EOS) {
g_print ("EOS!!\n");
if (g_main_loop_is_running (loop))
g_main_loop_quit (loop);
}
gst_message_unref (message);
return TRUE;
}
static gboolean
set_state (GstElement * element, GstElementState state,
GstElementStateReturn expected)
{
GstElementStateReturn ret;
gboolean res;
g_print ("setting state to %s, expecting %d...",
gst_element_state_get_name (state), expected);
ret = gst_element_set_state (element, state);
res = (ret == expected);
g_print ("%s\n", res ? "OK" : "failed");
return res;
}
static gboolean
get_state (GstElement * element, GstElementState exp_state,
GstElementState exp_pending, GTimeVal * timeval,
GstElementStateReturn expected)
{
GstElementStateReturn ret;
gboolean res;
GstElementState state, pending;
g_print ("getting state: expecting %s, %s, %d...",
gst_element_state_get_name (exp_state),
gst_element_state_get_name (exp_pending), expected);
ret = gst_element_get_state (element, &state, &pending, timeval);
res = (ret == expected);
res &= (state == exp_state);
res &= (pending == exp_pending);
if (res) {
g_print ("OK\n");
} else {
g_print ("failed, got %s, %s, %d\n",
gst_element_state_get_name (state),
gst_element_state_get_name (pending), ret);
}
return res;
}
static gboolean
commit_callback (GstClock * clock, GstClockTime time,
GstClockID id, GstElement * element)
{
g_print ("commiting state change..");
gst_element_commit_state (element);
return FALSE;
}
static gboolean
abort_callback (GstClock * clock, GstClockTime time,
GstClockID id, GstElement * element)
{
g_print ("aborting state change..");
gst_element_abort_state (element);
return FALSE;
}
gint
main (gint argc, gchar * argv[])
{
GstElement *fakesink;
GstBus *bus;
GTimeVal timeval;
GstClock *clock;
GstClockID id;
GstClockTime base;
GstClockReturn result;
gst_init (&argc, &argv);
loop = g_main_loop_new (NULL, FALSE);
bus = gst_bus_new ();
gst_bus_add_watch (bus, (GstBusHandler) message_received, NULL);
clock = gst_system_clock_obtain ();
g_assert (clock != NULL);
fakesink = gst_element_factory_make ("fakesink", "fakesink");
g_assert (fakesink);
gst_element_set_bus (fakesink, bus);
g_assert (set_state (fakesink, GST_STATE_READY, GST_STATE_SUCCESS));
g_assert (get_state (fakesink, GST_STATE_READY, GST_STATE_VOID_PENDING, NULL,
GST_STATE_SUCCESS));
g_assert (set_state (fakesink, GST_STATE_PAUSED, GST_STATE_ASYNC));
g_get_current_time (&timeval);
g_time_val_add (&timeval, G_USEC_PER_SEC * 1);
g_assert (get_state (fakesink, GST_STATE_READY, GST_STATE_PAUSED, &timeval,
GST_STATE_ASYNC));
g_assert (get_state (fakesink, GST_STATE_READY, GST_STATE_PAUSED, &timeval,
GST_STATE_ASYNC));
g_assert (set_state (fakesink, GST_STATE_READY, GST_STATE_SUCCESS));
g_assert (get_state (fakesink, GST_STATE_READY, GST_STATE_VOID_PENDING, NULL,
GST_STATE_SUCCESS));
g_assert (set_state (fakesink, GST_STATE_PAUSED, GST_STATE_ASYNC));
g_assert (get_state (fakesink, GST_STATE_READY, GST_STATE_PAUSED, &timeval,
GST_STATE_ASYNC));
g_print ("aborting state change..\n");
gst_element_abort_state (fakesink);
g_assert (get_state (fakesink, GST_STATE_READY, GST_STATE_PAUSED, &timeval,
GST_STATE_FAILURE));
g_assert (set_state (fakesink, GST_STATE_PAUSED, GST_STATE_ASYNC));
g_assert (get_state (fakesink, GST_STATE_READY, GST_STATE_PAUSED, &timeval,
GST_STATE_ASYNC));
g_print ("commiting state change..\n");
gst_element_commit_state (fakesink);
g_assert (get_state (fakesink, GST_STATE_PAUSED, GST_STATE_VOID_PENDING,
&timeval, GST_STATE_SUCCESS));
g_assert (set_state (fakesink, GST_STATE_READY, GST_STATE_SUCCESS));
g_assert (get_state (fakesink, GST_STATE_READY, GST_STATE_VOID_PENDING,
&timeval, GST_STATE_SUCCESS));
g_assert (set_state (fakesink, GST_STATE_PAUSED, GST_STATE_ASYNC));
base = gst_clock_get_time (clock);
id = gst_clock_new_single_shot_id (clock, base + 1 * GST_SECOND);
g_print ("waiting one second async id %p to abort state\n", id);
result =
gst_clock_id_wait_async (id, (GstClockCallback) abort_callback, fakesink);
gst_clock_id_unref (id);
g_assert (result == GST_CLOCK_OK);
g_assert (get_state (fakesink, GST_STATE_READY, GST_STATE_PAUSED, NULL,
GST_STATE_FAILURE));
g_assert (get_state (fakesink, GST_STATE_READY, GST_STATE_PAUSED, NULL,
GST_STATE_FAILURE));
g_assert (set_state (fakesink, GST_STATE_PAUSED, GST_STATE_ASYNC));
id = gst_clock_new_single_shot_id (clock, base + 1 * GST_SECOND);
g_print ("waiting one second async id %p to commit state\n", id);
result =
gst_clock_id_wait_async (id, (GstClockCallback) commit_callback,
fakesink);
gst_clock_id_unref (id);
g_assert (result == GST_CLOCK_OK);
g_assert (get_state (fakesink, GST_STATE_PAUSED, GST_STATE_VOID_PENDING, NULL,
GST_STATE_SUCCESS));
g_assert (get_state (fakesink, GST_STATE_PAUSED, GST_STATE_VOID_PENDING, NULL,
GST_STATE_SUCCESS));
g_print ("passed..\n");
gst_object_unref (GST_OBJECT (fakesink));
return 0;
}

131
testsuite/states/test2.c Normal file
View file

@ -0,0 +1,131 @@
/* GStreamer
* Copyright (C) <2005> Wim Taymans <wim@fluendo.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "unistd.h"
#include <gst/gst.h>
static GMainLoop *loop;
static gboolean
message_received (GstBus * bus, GstMessage * message, gpointer ignored)
{
g_print ("message %p\n", message);
if (message->type == GST_MESSAGE_EOS) {
g_print ("EOS!!\n");
if (g_main_loop_is_running (loop))
g_main_loop_quit (loop);
}
gst_message_unref (message);
return TRUE;
}
static gboolean
set_state (GstElement * element, GstElementState state,
GstElementStateReturn expected)
{
GstElementStateReturn ret;
gboolean res;
g_print ("setting state to %s, expecting %d...",
gst_element_state_get_name (state), expected);
ret = gst_element_set_state (element, state);
res = (ret == expected);
if (res) {
g_print ("OK\n");
} else {
g_print ("failed, got %d\n", ret);
}
return res;
}
static gboolean
get_state (GstElement * element, GstElementState exp_state,
GstElementState exp_pending, GTimeVal * timeval,
GstElementStateReturn expected)
{
GstElementStateReturn ret;
gboolean res;
GstElementState state, pending;
g_print ("getting state: expecting %s, %s, %d...",
gst_element_state_get_name (exp_state),
gst_element_state_get_name (exp_pending), expected);
ret = gst_element_get_state (element, &state, &pending, timeval);
res = (ret == expected);
res &= (state == exp_state);
res &= (pending == exp_pending);
if (res) {
g_print ("OK\n");
} else {
g_print ("failed, got %s, %s, %d\n",
gst_element_state_get_name (state),
gst_element_state_get_name (pending), ret);
}
return res;
}
gint
main (gint argc, gchar * argv[])
{
GstElement *fakesink;
GstBus *bus;
GTimeVal timeval;
GstClock *clock;
gst_init (&argc, &argv);
loop = g_main_loop_new (NULL, FALSE);
bus = gst_bus_new ();
gst_bus_add_watch (bus, (GstBusHandler) message_received, NULL);
clock = gst_system_clock_obtain ();
g_assert (clock != NULL);
fakesink = gst_element_factory_make ("fakesink", "fakesink");
g_assert (fakesink);
gst_element_set_bus (fakesink, bus);
g_assert (set_state (fakesink, GST_STATE_READY, GST_STATE_SUCCESS));
g_assert (get_state (fakesink, GST_STATE_READY, GST_STATE_VOID_PENDING, NULL,
GST_STATE_SUCCESS));
g_assert (set_state (fakesink, GST_STATE_PAUSED, GST_STATE_ASYNC));
g_assert (set_state (fakesink, GST_STATE_PLAYING, GST_STATE_ASYNC));
g_get_current_time (&timeval);
g_time_val_add (&timeval, G_USEC_PER_SEC * 1);
g_assert (get_state (fakesink, GST_STATE_READY, GST_STATE_PAUSED, &timeval,
GST_STATE_ASYNC));
g_print ("passed..\n");
gst_object_unref (GST_OBJECT (fakesink));
return 0;
}

136
testsuite/states/test3.c Normal file
View file

@ -0,0 +1,136 @@
/* GStreamer
* Copyright (C) <2005> Wim Taymans <wim@fluendo.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "unistd.h"
#include <gst/gst.h>
static GMainLoop *loop;
static gboolean
message_received (GstBus * bus, GstMessage * message, gpointer ignored)
{
g_print ("message %p\n", message);
if (message->type == GST_MESSAGE_EOS) {
g_print ("EOS!!\n");
if (g_main_loop_is_running (loop))
g_main_loop_quit (loop);
}
gst_message_unref (message);
return TRUE;
}
static gboolean
set_state (GstElement * element, GstElementState state,
GstElementStateReturn expected)
{
GstElementStateReturn ret;
gboolean res;
g_print ("setting state to %s, expecting %d...",
gst_element_state_get_name (state), expected);
ret = gst_element_set_state (element, state);
res = (ret == expected);
if (res) {
g_print ("OK\n");
} else {
g_print ("failed, got %d\n", ret);
}
return res;
}
static gboolean
get_state (GstElement * element, GstElementState exp_state,
GstElementState exp_pending, GTimeVal * timeval,
GstElementStateReturn expected)
{
GstElementStateReturn ret;
gboolean res;
GstElementState state, pending;
g_print ("getting state: expecting %s, %s, %d...",
gst_element_state_get_name (exp_state),
gst_element_state_get_name (exp_pending), expected);
ret = gst_element_get_state (element, &state, &pending, timeval);
res = (ret == expected);
res &= (state == exp_state);
res &= (pending == exp_pending);
if (res) {
g_print ("OK\n");
} else {
g_print ("failed, got %s, %s, %d\n",
gst_element_state_get_name (state),
gst_element_state_get_name (pending), ret);
}
return res;
}
gint
main (gint argc, gchar * argv[])
{
GstElement *bin;
GstBus *bus;
GstClock *clock;
gst_init (&argc, &argv);
loop = g_main_loop_new (NULL, FALSE);
bus = gst_bus_new ();
gst_bus_add_watch (bus, (GstBusHandler) message_received, NULL);
clock = gst_system_clock_obtain ();
g_assert (clock != NULL);
bin = gst_element_factory_make ("bin", "bin");
g_assert (bin);
gst_element_set_bus (bin, bus);
g_assert (set_state (bin, GST_STATE_READY, GST_STATE_SUCCESS));
g_assert (get_state (bin, GST_STATE_READY, GST_STATE_VOID_PENDING, NULL,
GST_STATE_SUCCESS));
g_assert (set_state (bin, GST_STATE_PAUSED, GST_STATE_SUCCESS));
g_assert (get_state (bin, GST_STATE_PAUSED, GST_STATE_VOID_PENDING, NULL,
GST_STATE_SUCCESS));
g_assert (set_state (bin, GST_STATE_PLAYING, GST_STATE_SUCCESS));
g_assert (get_state (bin, GST_STATE_PLAYING, GST_STATE_VOID_PENDING, NULL,
GST_STATE_SUCCESS));
g_assert (set_state (bin, GST_STATE_PAUSED, GST_STATE_SUCCESS));
g_assert (get_state (bin, GST_STATE_PAUSED, GST_STATE_VOID_PENDING, NULL,
GST_STATE_SUCCESS));
g_assert (set_state (bin, GST_STATE_READY, GST_STATE_SUCCESS));
g_assert (get_state (bin, GST_STATE_READY, GST_STATE_VOID_PENDING, NULL,
GST_STATE_SUCCESS));
g_print ("passed..\n");
gst_object_unref (GST_OBJECT (bin));
return 0;
}

230
testsuite/states/test4.c Normal file
View file

@ -0,0 +1,230 @@
/* GStreamer
* Copyright (C) <2005> Wim Taymans <wim@fluendo.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "unistd.h"
#include <gst/gst.h>
static GMainLoop *loop;
static gboolean
message_received (GstBus * bus, GstMessage * message, gpointer ignored)
{
g_print ("message %p\n", message);
if (message->type == GST_MESSAGE_EOS) {
g_print ("EOS!!\n");
if (g_main_loop_is_running (loop))
g_main_loop_quit (loop);
}
gst_message_unref (message);
return TRUE;
}
static gboolean
set_state (GstElement * element, GstElementState state,
GstElementStateReturn expected)
{
GstElementStateReturn ret;
gboolean res;
g_print ("setting %s state to %s, expecting %d...",
gst_element_get_name (element),
gst_element_state_get_name (state), expected);
ret = gst_element_set_state (element, state);
res = (ret == expected);
g_print ("%s\n", res ? "OK" : "failed");
return res;
}
static gboolean
get_state (GstElement * element, GstElementState exp_state,
GstElementState exp_pending, GTimeVal * timeval,
GstElementStateReturn expected)
{
GstElementStateReturn ret;
gboolean res;
GstElementState state, pending;
g_print ("getting state %s: expecting %s, %s, %d...",
gst_element_get_name (element),
gst_element_state_get_name (exp_state),
gst_element_state_get_name (exp_pending), expected);
ret = gst_element_get_state (element, &state, &pending, timeval);
res = (ret == expected);
res &= (state == exp_state);
res &= (pending == exp_pending);
if (res) {
g_print ("OK\n");
} else {
g_print ("failed, got %s, %s, %d\n",
gst_element_state_get_name (state),
gst_element_state_get_name (pending), ret);
}
return res;
}
static gboolean
commit_callback (GstClock * clock, GstClockTime time,
GstClockID id, GstElement * element)
{
g_print ("commiting state change..");
gst_element_commit_state (element);
return FALSE;
}
static gboolean
abort_callback (GstClock * clock, GstClockTime time,
GstClockID id, GstElement * element)
{
g_print ("aborting state change..");
gst_element_abort_state (element);
return FALSE;
}
gint
main (gint argc, gchar * argv[])
{
GstElement *fakesink, *bin;
GstBus *bus;
GTimeVal timeval;
GstClock *clock;
GstClockID id;
GstClockTime base;
GstClockReturn result;
gst_init (&argc, &argv);
loop = g_main_loop_new (NULL, FALSE);
bus = gst_bus_new ();
gst_bus_add_watch (bus, (GstBusHandler) message_received, NULL);
clock = gst_system_clock_obtain ();
g_assert (clock != NULL);
fakesink = gst_element_factory_make ("fakesink", "fakesink");
g_assert (fakesink);
bin = gst_element_factory_make ("bin", "bin");
g_assert (bin);
gst_bin_add (GST_BIN (bin), fakesink);
gst_element_set_bus (bin, bus);
g_assert (set_state (bin, GST_STATE_READY, GST_STATE_SUCCESS));
g_assert (get_state (bin, GST_STATE_READY, GST_STATE_VOID_PENDING, NULL,
GST_STATE_SUCCESS));
g_assert (get_state (fakesink, GST_STATE_READY, GST_STATE_VOID_PENDING, NULL,
GST_STATE_SUCCESS));
g_assert (set_state (fakesink, GST_STATE_NULL, GST_STATE_SUCCESS));
g_assert (get_state (bin, GST_STATE_READY, GST_STATE_VOID_PENDING, NULL,
GST_STATE_SUCCESS));
g_assert (get_state (fakesink, GST_STATE_NULL, GST_STATE_VOID_PENDING, NULL,
GST_STATE_SUCCESS));
g_assert (set_state (bin, GST_STATE_READY, GST_STATE_SUCCESS));
g_assert (get_state (bin, GST_STATE_READY, GST_STATE_VOID_PENDING, NULL,
GST_STATE_SUCCESS));
g_assert (get_state (fakesink, GST_STATE_READY, GST_STATE_VOID_PENDING, NULL,
GST_STATE_SUCCESS));
g_get_current_time (&timeval);
g_time_val_add (&timeval, G_USEC_PER_SEC / 2);
g_assert (set_state (fakesink, GST_STATE_PAUSED, GST_STATE_ASYNC));
g_assert (get_state (bin, GST_STATE_READY, GST_STATE_VOID_PENDING, &timeval,
GST_STATE_ASYNC));
g_time_val_add (&timeval, G_USEC_PER_SEC / 2);
g_assert (get_state (fakesink, GST_STATE_READY, GST_STATE_PAUSED, &timeval,
GST_STATE_ASYNC));
g_assert (get_state (bin, GST_STATE_READY, GST_STATE_VOID_PENDING, &timeval,
GST_STATE_ASYNC));
g_assert (set_state (fakesink, GST_STATE_READY, GST_STATE_SUCCESS));
g_assert (get_state (bin, GST_STATE_READY, GST_STATE_VOID_PENDING, NULL,
GST_STATE_SUCCESS));
g_assert (get_state (fakesink, GST_STATE_READY, GST_STATE_VOID_PENDING, NULL,
GST_STATE_SUCCESS));
g_assert (set_state (bin, GST_STATE_PAUSED, GST_STATE_ASYNC));
g_time_val_add (&timeval, G_USEC_PER_SEC / 2);
g_assert (get_state (bin, GST_STATE_READY, GST_STATE_PAUSED, &timeval,
GST_STATE_ASYNC));
g_time_val_add (&timeval, G_USEC_PER_SEC / 2);
g_assert (get_state (fakesink, GST_STATE_READY, GST_STATE_PAUSED, &timeval,
GST_STATE_ASYNC));
g_assert (set_state (bin, GST_STATE_READY, GST_STATE_SUCCESS));
g_assert (get_state (bin, GST_STATE_READY, GST_STATE_VOID_PENDING, &timeval,
GST_STATE_SUCCESS));
g_assert (get_state (fakesink, GST_STATE_READY, GST_STATE_VOID_PENDING,
&timeval, GST_STATE_SUCCESS));
g_assert (set_state (bin, GST_STATE_PAUSED, GST_STATE_ASYNC));
g_assert (set_state (fakesink, GST_STATE_READY, GST_STATE_SUCCESS));
g_time_val_add (&timeval, G_USEC_PER_SEC / 2);
g_assert (get_state (bin, GST_STATE_PAUSED, GST_STATE_VOID_PENDING, &timeval,
GST_STATE_SUCCESS));
g_assert (set_state (bin, GST_STATE_READY, GST_STATE_SUCCESS));
g_assert (get_state (bin, GST_STATE_READY, GST_STATE_VOID_PENDING, &timeval,
GST_STATE_SUCCESS));
g_assert (set_state (bin, GST_STATE_PAUSED, GST_STATE_ASYNC));
base = gst_clock_get_time (clock);
id = gst_clock_new_single_shot_id (clock, base + 1 * GST_SECOND);
g_print ("waiting one second async id %p to abort state\n", id);
result =
gst_clock_id_wait_async (id, (GstClockCallback) abort_callback, fakesink);
gst_clock_id_unref (id);
g_assert (result == GST_CLOCK_OK);
g_assert (get_state (bin, GST_STATE_READY, GST_STATE_PAUSED, NULL,
GST_STATE_FAILURE));
g_assert (set_state (bin, GST_STATE_PAUSED, GST_STATE_ASYNC));
base = gst_clock_get_time (clock);
id = gst_clock_new_single_shot_id (clock, base + 1 * GST_SECOND);
g_print ("waiting one second async id %p to commit state\n", id);
result =
gst_clock_id_wait_async (id, (GstClockCallback) commit_callback,
fakesink);
gst_clock_id_unref (id);
g_assert (result == GST_CLOCK_OK);
g_assert (get_state (bin, GST_STATE_PAUSED, GST_STATE_VOID_PENDING, NULL,
GST_STATE_SUCCESS));
g_print ("passed..\n");
gst_object_unref (GST_OBJECT (fakesink));
return 0;
}