Added GstBin test.

Original commit message from CVS:
Added GstBin test.
Added GstSystemClock test.
Implemented clock distribution code in GstBin.
Implemented iterate sinks method for future use.
Rearranged gstelement.h
Fix GstIterator comparison bug.
Moved some code to GstPipeline, mostly clocking related.
This commit is contained in:
Wim Taymans 2005-03-09 16:10:59 +00:00
parent c6a7adc9d4
commit 6cacf76cd9
19 changed files with 1159 additions and 155 deletions

View file

@ -1,3 +1,43 @@
2005-03-09 Wim Taymans <wim@fluendo.com>
* check/Makefile.am:
* check/gst/gstbin.c: (START_TEST), (gst_bin_suite), (main):
* check/gst/gstsystemclock.c: (START_TEST), (gst_clock_debug),
(ok_callback), (error_callback), (gst_systemclock_suite), (main):
* gst/gstbin.c: (gst_bin_class_init), (gst_bin_set_index_func),
(gst_bin_set_clock_func), (gst_bin_get_clock_func),
(gst_bin_add_func), (gst_bin_add), (gst_bin_remove_func),
(gst_bin_remove), (gst_bin_iterate_recurse_up),
(bin_element_is_sink), (gst_bin_iterate_sinks),
(gst_bin_iterate_all_by_interface):
* gst/gstbin.h:
* gst/gstelement.c: (gst_element_init), (gst_element_error_full),
(gst_element_change_state), (gst_element_dispose),
(gst_element_finalize), (gst_element_set_loop_function):
* gst/gstelement.h:
* gst/gstiterator.c: (find_custom_fold_func):
* gst/gstpad.c: (_gst_pad_default_fixate_foreach),
(gst_pad_collectv), (gst_pad_collect_valist),
(gst_pad_template_new):
* gst/gstpipeline.c: (gst_pipeline_class_init),
(gst_pipeline_dispose), (gst_pipeline_set_property),
(gst_pipeline_get_property), (gst_pipeline_get_clock_func),
(gst_pipeline_get_clock), (gst_pipeline_use_clock),
(gst_pipeline_set_clock), (gst_pipeline_auto_clock):
* gst/gstutils.h:
* gst/schedulers/entryscheduler.c:
* gst/schedulers/gstbasicscheduler.c:
(gst_basic_scheduler_cothreaded_chain),
(gst_basic_scheduler_chain_add_element):
* testsuite/bins/interface.c: (main):
Added GstBin test.
Added GstSystemClock test.
Implemented clock distribution code in GstBin.
Implemented iterate sinks method for future use.
Rearranged gstelement.h
Fix GstIterator comparison bug.
Moved some code to GstPipeline, mostly clocking related.
2005-03-09 Wim Taymans <wim@fluendo.com>
* configure.ac:

View file

@ -19,10 +19,12 @@ install-pluginLTLIBRARIES:
CLEANFILES = core.*
TESTS = $(top_builddir)/tools/gst-register-@GST_MAJORMINOR@ \
gst/gstcaps \
gst/gstdata \
gst/gstiterator \
gst/gstobject \
gst/gstbin \
gst/gstcaps \
gst/gstdata \
gst/gstiterator \
gst/gstobject \
gst/gstsystemclock \
gst-libs/gdp
check_PROGRAMS = $(TESTS)

110
check/gst/gstbin.c Normal file
View file

@ -0,0 +1,110 @@
/* GStreamer
* Copyright (C) 2005 Wim Taymans <wim@fluendo.com>
*
* gstbin.c: Unit test for GstBin
*
* 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 "../gstcheck.h"
START_TEST (test_interface)
{
GstBin *bin, *bin2;
GstElement *filesrc;
GstIterator *it;
gpointer item;
bin = GST_BIN (gst_bin_new (NULL));
fail_unless (bin != NULL, "Could not create bin");
filesrc = gst_element_factory_make ("filesrc", NULL);
fail_unless (filesrc != NULL, "Could not create filesrc");
fail_unless (GST_IS_URI_HANDLER (filesrc), "Filesrc not a URI handler");
gst_bin_add (bin, filesrc);
fail_unless (gst_bin_get_by_interface (bin, GST_TYPE_URI_HANDLER) == filesrc);
it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER);
fail_unless (it != NULL);
fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
fail_unless (item == (gpointer) filesrc);
fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
gst_iterator_free (it);
gst_bin_add_many (bin,
gst_element_factory_make ("identity", NULL),
gst_element_factory_make ("identity", NULL),
gst_element_factory_make ("identity", NULL), NULL);
fail_unless (gst_bin_get_by_interface (bin, GST_TYPE_URI_HANDLER) == filesrc);
it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER);
fail_unless (it != NULL);
fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
fail_unless (item == (gpointer) filesrc);
fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
gst_iterator_free (it);
bin2 = bin;
bin = GST_BIN (gst_bin_new (NULL));
fail_unless (bin != NULL);
gst_bin_add_many (bin,
gst_element_factory_make ("identity", NULL),
gst_element_factory_make ("identity", NULL),
GST_ELEMENT (bin2), gst_element_factory_make ("identity", NULL), NULL);
fail_unless (gst_bin_get_by_interface (bin, GST_TYPE_URI_HANDLER) == filesrc);
it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER);
fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
fail_unless (item == (gpointer) filesrc);
fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
gst_iterator_free (it);
gst_bin_add (bin, gst_element_factory_make ("filesrc", NULL));
gst_bin_add (bin2, gst_element_factory_make ("filesrc", NULL));
it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER);
fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
gst_iterator_free (it);
g_object_unref (bin);
}
END_TEST Suite * gst_bin_suite (void)
{
Suite *s = suite_create ("GstBin");
TCase *tc_chain = tcase_create ("bin tests");
suite_add_tcase (s, tc_chain);
tcase_add_test (tc_chain, test_interface);
return s;
}
int
main (int argc, char **argv)
{
int nf;
Suite *s = gst_bin_suite ();
SRunner *sr = srunner_create (s);
gst_check_init (&argc, &argv);
srunner_run_all (sr, CK_NORMAL);
nf = srunner_ntests_failed (sr);
srunner_free (sr);
return nf;
}

221
check/gst/gstsystemclock.c Normal file
View file

@ -0,0 +1,221 @@
/* GStreamer
* Copyright (C) 2005 Wim Taymans <wim@fluendo.com>
*
* gstsystemclock.c: Unit test for GstSystemClock
*
* 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 "../gstcheck.h"
START_TEST (test_signedness)
{
GstClockTime time[] = { 0, 1, G_MAXUINT64 / GST_SECOND };
GstClockTimeDiff diff[] =
{ 0, 1, -1, G_MAXINT64 / GST_SECOND, G_MININT64 / GST_SECOND };
guint i;
for (i = 0; i < G_N_ELEMENTS (time); i++) {
fail_if (time[i] != (time[i] * GST_SECOND / GST_SECOND));
}
for (i = 0; i < G_N_ELEMENTS (diff); i++) {
fail_if (diff[i] != (diff[i] * GST_SECOND / GST_SECOND));
}
}
END_TEST
#define TIME_UNIT GST_SECOND
static void
gst_clock_debug (GstClock * clock)
{
GstClockTime time;
time = gst_clock_get_time (clock);
g_message ("Clock info: time %" G_GUINT64_FORMAT "\n", time);
}
static gboolean
ok_callback (GstClock * clock, GstClockTime time,
GstClockID id, gpointer user_data)
{
g_message ("unlocked async id %p\n", id);
return FALSE;
}
static gboolean
error_callback (GstClock * clock, GstClockTime time,
GstClockID id, gpointer user_data)
{
g_message ("unlocked unscheduled async id %p, this is wrong\n", id);
fail_if (TRUE);
return FALSE;
}
START_TEST (test_single_shot)
{
GstClock *clock;
GstClockID id, id2;
GstClockTime base;
GstClockReturn result;
clock = gst_system_clock_obtain ();
fail_unless (clock != NULL, "Could not create instance of GstSystemClock");
gst_clock_debug (clock);
base = gst_clock_get_time (clock);
id = gst_clock_new_single_shot_id (clock, base + TIME_UNIT);
fail_unless (id != NULL, "Could not create single shot id");
g_message ("waiting one second\n");
result = gst_clock_id_wait (id, NULL);
gst_clock_debug (clock);
fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
g_message ("waiting in the past\n");
result = gst_clock_id_wait (id, NULL);
gst_clock_debug (clock);
fail_unless (result == GST_CLOCK_EARLY, "Waiting did not return EARLY");
gst_clock_id_unref (id);
id = gst_clock_new_single_shot_id (clock, base + 2 * TIME_UNIT);
g_message ("waiting one second async id %p\n", id);
result = gst_clock_id_wait_async (id, ok_callback, NULL);
gst_clock_id_unref (id);
fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
g_usleep (2 * G_USEC_PER_SEC);
id = gst_clock_new_single_shot_id (clock, base + 5 * TIME_UNIT);
g_message ("waiting one second async, with cancel on id %p\n", id);
result = gst_clock_id_wait_async (id, error_callback, NULL);
fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
g_usleep (G_USEC_PER_SEC / 2);
g_message ("cancel id %p after 0.5 seconds\n", id);
gst_clock_id_unschedule (id);
gst_clock_id_unref (id);
g_message ("canceled id %p\n", id);
g_message ("waiting multiple one second async, with cancel\n");
id = gst_clock_new_single_shot_id (clock, base + 5 * TIME_UNIT);
id2 = gst_clock_new_single_shot_id (clock, base + 6 * TIME_UNIT);
g_message ("waiting id %p\n", id);
result = gst_clock_id_wait_async (id, ok_callback, NULL);
fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
gst_clock_id_unref (id);
g_message ("waiting id %p\n", id2);
result = gst_clock_id_wait_async (id2, error_callback, NULL);
fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
g_usleep (G_USEC_PER_SEC / 2);
g_message ("cancel id %p after 0.5 seconds\n", id2);
gst_clock_id_unschedule (id2);
g_message ("canceled id %p\n", id2);
gst_clock_id_unref (id2);
g_usleep (2 * G_USEC_PER_SEC);
}
END_TEST
START_TEST (test_periodic_shot)
{
GstClock *clock;
GstClockID id, id2;
GstClockTime base;
GstClockReturn result;
clock = gst_system_clock_obtain ();
fail_unless (clock != NULL, "Could not create instance of GstSystemClock");
gst_clock_debug (clock);
base = gst_clock_get_time (clock);
/* signal every half a second */
id = gst_clock_new_periodic_id (clock, base + TIME_UNIT, TIME_UNIT / 2);
fail_unless (id != NULL, "Could not create periodic id");
g_message ("waiting one second\n");
result = gst_clock_id_wait (id, NULL);
gst_clock_debug (clock);
fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
g_message ("waiting for the next\n");
result = gst_clock_id_wait (id, NULL);
gst_clock_debug (clock);
fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
g_message ("waiting for the next async %p\n", id);
result = gst_clock_id_wait_async (id, ok_callback, NULL);
fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
g_usleep (2 * G_USEC_PER_SEC);
g_message ("waiting some more for the next async %p\n", id);
result = gst_clock_id_wait_async (id, ok_callback, NULL);
fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
g_usleep (2 * G_USEC_PER_SEC);
id2 = gst_clock_new_periodic_id (clock, base + TIME_UNIT, TIME_UNIT / 2);
fail_unless (id2 != NULL, "Could not create second periodic id");
g_message ("waiting some more for another async %p\n", id2);
result = gst_clock_id_wait_async (id2, ok_callback, NULL);
fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
g_usleep (2 * G_USEC_PER_SEC);
g_message ("unschedule %p\n", id);
gst_clock_id_unschedule (id);
/* entry cannot be used again */
result = gst_clock_id_wait_async (id, error_callback, NULL);
fail_unless (result == GST_CLOCK_UNSCHEDULED,
"Waiting did not return UNSCHEDULED");
result = gst_clock_id_wait (id, NULL);
fail_unless (result == GST_CLOCK_UNSCHEDULED,
"Waiting did not return UNSCHEDULED");
g_usleep (2 * G_USEC_PER_SEC);
}
END_TEST Suite * gst_systemclock_suite (void)
{
Suite *s = suite_create ("GstSystemClock");
TCase *tc_chain = tcase_create ("waiting");
/* increase timeout */
tcase_set_timeout (tc_chain, 20);
suite_add_tcase (s, tc_chain);
tcase_add_test (tc_chain, test_signedness);
tcase_add_test (tc_chain, test_single_shot);
tcase_add_test (tc_chain, test_periodic_shot);
return s;
}
int
main (int argc, char **argv)
{
int nf;
Suite *s = gst_systemclock_suite ();
SRunner *sr = srunner_create (s);
gst_check_init (&argc, &argv);
srunner_run_all (sr, CK_NORMAL);
nf = srunner_ntests_failed (sr);
srunner_free (sr);
return nf;
}

View file

@ -60,20 +60,20 @@ static void gst_bin_dispose (GObject * object);
static GstElementStateReturn gst_bin_change_state (GstElement * element);
static GstElementStateReturn gst_bin_change_state_norecurse (GstBin * bin);
#ifndef GST_DISABLE_INDEX
static void gst_bin_set_index (GstElement * element, GstIndex * index);
#endif
static gboolean gst_bin_add_func (GstBin * bin, GstElement * element);
static gboolean gst_bin_remove_func (GstBin * bin, GstElement * element);
#ifndef GST_DISABLE_INDEX
static void gst_bin_set_index_func (GstElement * element, GstIndex * index);
#endif
static GstClock *gst_bin_get_clock_func (GstElement * element);
static void gst_bin_set_clock_func (GstElement * element, GstClock * clock);
static void gst_bin_child_state_change_func (GstBin * bin,
GstElementState oldstate, GstElementState newstate, GstElement * child);
GstElementStateReturn gst_bin_set_state (GstElement * element,
GstElementState state);
static GstClock *gst_bin_get_clock_func (GstElement * element);
static void gst_bin_set_clock_func (GstElement * element, GstClock * clock);
static gboolean gst_bin_iterate_func (GstBin * bin);
#ifndef GST_DISABLE_LOADSAVE
@ -180,11 +180,14 @@ gst_bin_class_init (GstBinClass * klass)
gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_bin_change_state);
gstelement_class->set_state = GST_DEBUG_FUNCPTR (gst_bin_set_state);
#ifndef GST_DISABLE_INDEX
gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_bin_set_index);
gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_bin_set_index_func);
#endif
gstelement_class->get_clock = GST_DEBUG_FUNCPTR (gst_bin_get_clock_func);
gstelement_class->set_clock = GST_DEBUG_FUNCPTR (gst_bin_set_clock_func);
klass->add_element = GST_DEBUG_FUNCPTR (gst_bin_add_func);
klass->remove_element = GST_DEBUG_FUNCPTR (gst_bin_remove_func);
klass->child_state_change =
GST_DEBUG_FUNCPTR (gst_bin_child_state_change_func);
klass->iterate = GST_DEBUG_FUNCPTR (gst_bin_iterate_func);
@ -227,73 +230,13 @@ gst_bin_new (const gchar * name)
return gst_element_factory_make ("bin", name);
}
static GstClock *
gst_bin_get_clock_func (GstElement * element)
{
if (GST_ELEMENT_SCHEDULER (element))
return gst_scheduler_get_clock (GST_ELEMENT_SCHEDULER (element));
return NULL;
}
static void
gst_bin_set_clock_func (GstElement * element, GstClock * clock)
{
if (GST_ELEMENT_SCHEDULER (element))
gst_scheduler_use_clock (GST_ELEMENT_SCHEDULER (element), clock);
}
/**
* gst_bin_get_clock:
* @bin: a #GstBin to get the clock of
/* set the index on all elements in this bin
*
* Gets the current clock of the (scheduler of the) bin.
*
* Returns: the #GstClock of the bin
* MT safe
*/
GstClock *
gst_bin_get_clock (GstBin * bin)
{
g_return_val_if_fail (bin != NULL, NULL);
g_return_val_if_fail (GST_IS_BIN (bin), NULL);
return gst_bin_get_clock_func (GST_ELEMENT (bin));
}
/**
* gst_bin_use_clock:
* @bin: the bin to set the clock for
* @clock: the clock to use.
*
* Force the bin to use the given clock. Use NULL to
* force it to use no clock at all.
*/
void
gst_bin_use_clock (GstBin * bin, GstClock * clock)
{
g_return_if_fail (GST_IS_BIN (bin));
gst_bin_set_clock_func (GST_ELEMENT (bin), clock);
}
/**
* gst_bin_auto_clock:
* @bin: the bin to autoclock
*
* Let the bin select a clock automatically.
*/
void
gst_bin_auto_clock (GstBin * bin)
{
g_return_if_fail (GST_IS_BIN (bin));
if (GST_ELEMENT_SCHEDULER (bin))
gst_scheduler_auto_clock (GST_ELEMENT_SCHEDULER (bin));
}
#ifndef GST_DISABLE_INDEX
static void
gst_bin_set_index (GstElement * element, GstIndex * index)
gst_bin_set_index_func (GstElement * element, GstIndex * index)
{
GstBin *bin;
GList *children;
@ -310,6 +253,53 @@ gst_bin_set_index (GstElement * element, GstIndex * index)
}
#endif
/* set the clock on all elements in this bin
*
* MT safe
*/
static void
gst_bin_set_clock_func (GstElement * element, GstClock * clock)
{
GList *children;
GstBin *bin;
bin = GST_BIN (element);
GST_LOCK (bin);
for (children = bin->children; children; children = g_list_next (children)) {
GstElement *child = GST_ELEMENT (children->data);
gst_element_set_clock (child, clock);
}
GST_UNLOCK (bin);
}
/* get the clock for this bin by asking all of the children in this bin
*
* MT safe
*/
static GstClock *
gst_bin_get_clock_func (GstElement * element)
{
GstClock *result = NULL;
GstBin *bin;
GList *children;
bin = GST_BIN (element);
GST_LOCK (bin);
for (children = bin->children; children; children = g_list_next (children)) {
GstElement *child = GST_ELEMENT (children->data);
result = gst_element_get_clock (child);
if (result)
break;
}
GST_UNLOCK (bin);
return result;
}
static void
gst_bin_set_element_sched (GstElement * element, GstScheduler * sched)
{
@ -741,6 +731,114 @@ 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
*
* MT safe
*/
static gint
bin_element_is_sink (GstElement * child, GstBin * bin)
{
gint ret = 1;
/* we lock the child here for the remainder of the function to
* get its pads and name safely. */
GST_LOCK (child);
/* check if this is a sink element, these are the elements
* without (linked) source pads. */
if (child->numsrcpads == 0) {
/* shortcut */
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
"adding child %s as sink", GST_OBJECT_NAME (child));
ret = 0;
} else {
/* loop over all pads, try to figure out if this element
* is a sink because it has no linked source pads */
GList *pads;
gboolean connected_src = FALSE;
for (pads = child->srcpads; pads; pads = g_list_next (pads)) {
GstPad *peer;
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;
}
}
}
if (connected_src) {
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
"not adding child %s as sink: linked source pads",
GST_OBJECT_NAME (child));
} else {
GST_CAT_DEBUG_OBJECT (GST_CAT_STATES, bin,
"adding child %s as sink since it has unlinked source pads in this bin",
GST_OBJECT_NAME (child));
ret = 0;
}
}
GST_UNLOCK (child);
/* we did not find the element, need to release the ref
* added by the iterator */
if (ret == 1)
gst_object_unref (GST_OBJECT (child));
return ret;
}
/**
* gst_bin_iterate_sinks:
* @bin: #Gstbin to iterate on
*
* Get an iterator for the sink elements in this bin.
* Each element will have its refcount increased, so unref
* after usage.
*
* Returns: a #GstIterator of #GstElements. gst_iterator_free after use.
*
* MT safe.
*/
GstIterator *
gst_bin_iterate_sinks (GstBin * bin)
{
GstIterator *children;
GstIterator *result;
g_return_val_if_fail (GST_IS_BIN (bin), NULL);
children = gst_bin_iterate_elements (bin);
result = gst_iterator_filter (children,
(GCompareFunc) bin_element_is_sink, bin);
return result;
}
/**
* gst_bin_child_state_change:
* @bin: #GstBin with the child
@ -1197,7 +1295,6 @@ gst_bin_iterate_all_by_interface (GstBin * bin, GType interface)
children = gst_bin_iterate_recurse (bin);
result = gst_iterator_filter (children, (GCompareFunc) compare_interface,
GINT_TO_POINTER (interface));
gst_iterator_free (children);
return result;
}

View file

@ -60,8 +60,7 @@ GST_EXPORT GType _gst_bin_type;
* and (un)set using GST_FLAG_SET () and GST_FLAG_UNSET ().
*/
typedef enum {
GST_BIN_FLAG_FIXED_CLOCK = GST_ELEMENT_FLAG_LAST,
GST_BIN_FLAG_MANAGER,
GST_BIN_FLAG_MANAGER = GST_ELEMENT_FLAG_LAST,
GST_BIN_SELF_SCHEDULABLE,
GST_BIN_STATE_LOCKED,
/* padding */

View file

@ -252,7 +252,7 @@ gst_element_init (GstElement * element)
element->srcpads = NULL;
element->sinkpads = NULL;
element->loopfunc = NULL;
element->sched = NULL;
element->scheduler = NULL;
element->clock = NULL;
element->sched_private = NULL;
element->state_lock = g_mutex_new ();
@ -1766,8 +1766,8 @@ void gst_element_error_full
GST_ELEMENT_NAME (element), sent_message);
/* tell the scheduler */
if (element->sched) {
gst_scheduler_error (element->sched, element);
if (GST_ELEMENT_SCHEDULER (element)) {
gst_scheduler_error (GST_ELEMENT_SCHEDULER (element), element);
}
if (GST_STATE (element) == GST_STATE_PLAYING) {
@ -2200,9 +2200,9 @@ gst_element_change_state (GstElement * element)
gst_element_state_get_name (GST_STATE (element)));
/* tell the scheduler if we have one */
if (element->sched) {
if (gst_scheduler_state_transition (element->sched, element,
old_transition) != GST_STATE_SUCCESS) {
if (GST_ELEMENT_SCHEDULER (element)) {
if (gst_scheduler_state_transition (GST_ELEMENT_SCHEDULER (element),
element, old_transition) != GST_STATE_SUCCESS) {
GST_CAT_INFO_OBJECT (GST_CAT_STATES, element,
"scheduler could not change state");
goto failure;
@ -2263,13 +2263,17 @@ gst_element_dispose (GObject * object)
while (element->pads) {
gst_element_remove_pad (element, GST_PAD (element->pads->data));
}
if (G_UNLIKELY (element->pads != 0)) {
g_critical ("could not remove pads from element %s",
GST_STR_NULL (GST_OBJECT_NAME (object)));
}
element->numsrcpads = 0;
element->numsinkpads = 0;
element->numpads = 0;
gst_object_replace ((GstObject **) & element->sched, NULL);
GST_LOCK (element);
gst_object_replace ((GstObject **) & element->scheduler, 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);
}
@ -2279,8 +2283,16 @@ 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);
g_cond_free (element->state_cond);
GST_CAT_INFO_OBJECT (GST_CAT_REFCOUNTING, element, "finalize parent");
G_OBJECT_CLASS (parent_class)->finalize (object);
}

View file

@ -137,7 +137,7 @@ typedef enum
#define GST_ELEMENT_NAME(obj) (GST_OBJECT_NAME(obj))
#define GST_ELEMENT_PARENT(obj) (GST_OBJECT_PARENT(obj))
#define GST_ELEMENT_SCHEDULER(obj) (GST_ELEMENT_CAST(obj)->sched)
#define GST_ELEMENT_SCHEDULER(obj) (GST_ELEMENT_CAST(obj)->scheduler)
#define GST_ELEMENT_CLOCK(obj) (GST_ELEMENT_CAST(obj)->clock)
#define GST_ELEMENT_PADS(obj) (GST_ELEMENT_CAST(obj)->pads)
@ -183,7 +183,7 @@ typedef void (*GstElementLoopFunction) (GstElement *element);
#define GST_STATE_SIGNAL(elem) g_cond_signal (GST_STATE_GET_COND (elem));
#define GST_STATE_BROADCAST(elem) g_cond_broadcast (GST_STATE_GET_COND (elem));
struct _GstElement
struct _GstElement
{
GstObject object;
@ -198,7 +198,7 @@ struct _GstElement
/*< public >*/ /* with LOCK */
/* scheduling */
GstElementLoopFunction loopfunc;
GstScheduler *sched;
GstScheduler *scheduler;
/* private pointer for the scheduler */
gpointer sched_private;
@ -246,7 +246,7 @@ struct _GstElementClass
void (*found_tag) (GstElement *element, GstElement *source, const GstTagList *tag_list);
/*< protected >*/
/* vtable*/
/* vtable */
/* request/release pads */
GstPad* (*request_new_pad) (GstElement *element, GstPadTemplate *templ, const gchar* name);
@ -278,6 +278,7 @@ struct _GstElementClass
const GstQueryType* (*get_query_types) (GstElement *element);
gboolean (*query) (GstElement *element, GstQueryType type,
GstFormat *format, gint64 *value);
/*< private >*/
gpointer _gst_reserved[GST_PADDING];
};
@ -317,7 +318,6 @@ gboolean gst_element_is_indexable (GstElement *element);
void gst_element_set_index (GstElement *element, GstIndex *index);
GstIndex* gst_element_get_index (GstElement *element);
/* scheduling */
void gst_element_set_loop_function (GstElement *element,
GstElementLoopFunction loop);
@ -366,8 +366,6 @@ void gst_element_default_error (GObject *object, GstObject *orig, GError *err
#define gst_element_default_deep_notify gst_object_default_deep_notify
/* state management */
void gst_element_set_eos (GstElement *element);
gboolean gst_element_is_locked_state (GstElement *element);
gboolean gst_element_set_locked_state (GstElement *element, gboolean locked_state);
gboolean gst_element_sync_state_with_parent (GstElement *element);
@ -377,6 +375,8 @@ GstElementStateReturn gst_element_set_state (GstElement *element, GstElementSta
void gst_element_wait_state_change (GstElement *element);
void gst_element_set_eos (GstElement *element);
/* factory management */
GstElementFactory* gst_element_get_factory (GstElement *element);
@ -459,4 +459,3 @@ void __gst_element_factory_add_interface (GstElementFactory *elementfactory,
G_END_DECLS
#endif /* __GST_ELEMENT_H__ */

View file

@ -506,7 +506,7 @@ typedef struct
static gboolean
find_custom_fold_func (gpointer item, GValue * ret, FindCustomFoldData * data)
{
if (data->func (item, data->user_data)) {
if (data->func (item, data->user_data) == 0) {
g_value_set_pointer (ret, item);
return FALSE;
} else {

View file

@ -3587,16 +3587,6 @@ gst_pad_template_new (const gchar * name_template,
if (!name_is_valid (name_template, presence))
return NULL;
#if 0
#ifdef USE_POISONING
if (caps) {
GstCaps *newcaps = gst_caps_copy (caps);
gst_caps_unref (caps);
caps = newcaps;
}
#endif
#endif
new = g_object_new (gst_pad_template_get_type (),
"name", name_template, NULL);

View file

@ -25,6 +25,7 @@
#include "gstpipeline.h"
#include "gstinfo.h"
#include "gstscheduler.h"
#include "gstsystemclock.h"
static GstElementDetails gst_pipeline_details =
GST_ELEMENT_DETAILS ("Pipeline object",
@ -43,8 +44,10 @@ enum
#define DEFAULT_PLAY_TIMEOUT (2*GST_SECOND)
enum
{
ARG_0
/* FILL ME */
ARG_0,
ARG_DELAY,
ARG_PLAY_TIMEOUT,
/* FILL ME */
};
@ -53,7 +56,12 @@ static void gst_pipeline_class_init (gpointer g_class, gpointer class_data);
static void gst_pipeline_init (GTypeInstance * instance, gpointer g_class);
static void gst_pipeline_dispose (GObject * object);
static void gst_pipeline_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_pipeline_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec);
static GstClock *gst_pipeline_get_clock_func (GstElement * element);
static GstElementStateReturn gst_pipeline_change_state (GstElement * element);
static GstBinClass *parent_class = NULL;
@ -102,10 +110,24 @@ gst_pipeline_class_init (gpointer g_class, gpointer class_data)
parent_class = g_type_class_peek_parent (klass);
gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_pipeline_set_property);
gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_pipeline_get_property);
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_DELAY,
g_param_spec_uint64 ("delay", "Delay",
"Expected delay needed for elements "
"to spin up to PLAYING in nanoseconds", 0, G_MAXUINT64, DEFAULT_DELAY,
G_PARAM_READWRITE));
g_object_class_install_property (G_OBJECT_CLASS (klass), ARG_PLAY_TIMEOUT,
g_param_spec_uint64 ("play-timeout", "Play Timeout",
"Max timeout for going " "to PLAYING in nanoseconds", 0, G_MAXUINT64,
DEFAULT_PLAY_TIMEOUT, G_PARAM_READWRITE));
gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_pipeline_dispose);
gstelement_class->change_state =
GST_DEBUG_FUNCPTR (gst_pipeline_change_state);
gstelement_class->get_clock = GST_DEBUG_FUNCPTR (gst_pipeline_get_clock_func);
}
static void
@ -134,15 +156,55 @@ static void
gst_pipeline_dispose (GObject * object)
{
GstPipeline *pipeline = GST_PIPELINE (object);
GstScheduler *sched;
g_assert (GST_IS_SCHEDULER (GST_ELEMENT_SCHEDULER (pipeline)));
sched = GST_ELEMENT_SCHEDULER (pipeline);
gst_scheduler_reset (GST_ELEMENT_SCHEDULER (object));
gst_object_replace ((GstObject **) & pipeline->fixed_clock, NULL);
gst_scheduler_reset (sched);
G_OBJECT_CLASS (parent_class)->dispose (object);
}
static void
gst_pipeline_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
GstPipeline *pipeline = GST_PIPELINE (object);
GST_LOCK (pipeline);
switch (prop_id) {
case ARG_DELAY:
pipeline->delay = g_value_get_uint64 (value);
break;
case ARG_PLAY_TIMEOUT:
pipeline->play_timeout = g_value_get_uint64 (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
GST_UNLOCK (pipeline);
}
static void
gst_pipeline_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec)
{
GstPipeline *pipeline = GST_PIPELINE (object);
GST_LOCK (pipeline);
switch (prop_id) {
case ARG_DELAY:
g_value_set_uint64 (value, pipeline->delay);
break;
case ARG_PLAY_TIMEOUT:
g_value_set_uint64 (value, pipeline->play_timeout);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
GST_UNLOCK (pipeline);
}
/**
* gst_pipeline_new:
* @name: name of new pipeline
@ -179,3 +241,125 @@ gst_pipeline_change_state (GstElement * element)
return GST_STATE_SUCCESS;
}
static GstClock *
gst_pipeline_get_clock_func (GstElement * element)
{
GstClock *clock = NULL;
GstPipeline *pipeline = GST_PIPELINE (element);
/* if we have a fixed clock, use that one */
GST_LOCK (pipeline);
if (GST_FLAG_IS_SET (pipeline, GST_PIPELINE_FLAG_FIXED_CLOCK)) {
clock = pipeline->fixed_clock;
gst_object_ref (GST_OBJECT (clock));
GST_UNLOCK (pipeline);
GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline using fixed clock %p (%s)",
clock, clock ? GST_STR_NULL (GST_OBJECT_NAME (clock)) : "-");
} else {
GST_UNLOCK (pipeline);
clock =
GST_ELEMENT_CLASS (parent_class)->get_clock (GST_ELEMENT (pipeline));
/* no clock, use a system clock */
if (!clock) {
clock = gst_system_clock_obtain ();
/* we unref since this function is not supposed to increase refcount
* of clock object returned; this is ok since the systemclock always
* has a refcount of at least one in the current code. */
gst_object_unref (GST_OBJECT (clock));
GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline obtained system clock: %p (%s)",
clock, clock ? GST_STR_NULL (GST_OBJECT_NAME (clock)) : "-");
} else {
GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline obtained clock: %p (%s)",
clock, clock ? GST_STR_NULL (GST_OBJECT_NAME (clock)) : "-");
}
}
return clock;
}
/**
* gst_pipeline_get_clock:
* @pipeline: the pipeline
*
* Gets the current clock used by the pipeline.
*
* Returns: a GstClock
*/
GstClock *
gst_pipeline_get_clock (GstPipeline * pipeline)
{
g_return_val_if_fail (GST_IS_PIPELINE (pipeline), NULL);
return gst_pipeline_get_clock_func (GST_ELEMENT (pipeline));
}
/**
* gst_pipeline_use_clock:
* @pipeline: the pipeline
* @clock: the clock to use
*
* Force the pipeline to use the given clock. The pipeline will
* always use the given clock even if new clock providers are added
* to this pipeline.
*
* MT safe.
*/
void
gst_pipeline_use_clock (GstPipeline * pipeline, GstClock * clock)
{
g_return_if_fail (GST_IS_PIPELINE (pipeline));
GST_LOCK (pipeline);
GST_FLAG_SET (pipeline, GST_PIPELINE_FLAG_FIXED_CLOCK);
gst_object_replace ((GstObject **) & pipeline->fixed_clock,
(GstObject *) clock);
GST_LOCK (pipeline);
GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline using fixed clock %p (%s)", clock,
(clock ? GST_OBJECT_NAME (clock) : "nil"));
}
/**
* gst_pipeline_set_clock:
* @pipeline: the pipeline
* @clock: the clock to set
*
* Set the clock for the pipeline. The clock will be distributed
* to all the elements managed by the pipeline.
*
* MT safe.
*/
void
gst_pipeline_set_clock (GstPipeline * pipeline, GstClock * clock)
{
g_return_if_fail (pipeline != NULL);
g_return_if_fail (GST_IS_PIPELINE (pipeline));
GST_ELEMENT_CLASS (parent_class)->set_clock (GST_ELEMENT (pipeline), clock);
}
/**
* gst_pipeline_auto_clock:
* @pipeline: the pipeline
*
* Let the pipeline select a clock automatically.
*
* MT safe.
*/
void
gst_pipeline_auto_clock (GstPipeline * pipeline)
{
g_return_if_fail (pipeline != NULL);
g_return_if_fail (GST_IS_PIPELINE (pipeline));
GST_LOCK (pipeline);
GST_FLAG_UNSET (pipeline, GST_PIPELINE_FLAG_FIXED_CLOCK);
gst_object_replace ((GstObject **) & pipeline->fixed_clock, NULL);
GST_UNLOCK (pipeline);
GST_CAT_DEBUG (GST_CAT_CLOCK, "pipeline using automatic clock");
}

View file

@ -277,7 +277,6 @@ void gst_bin_remove_many (GstBin *bin, GstElement *eleme
/* buffer functions */
GstBuffer * gst_buffer_merge (GstBuffer * buf1, GstBuffer * buf2);
void gst_buffer_stamp (GstBuffer * dest, const GstBuffer * src);
void gst_buffer_stamp (GstBuffer * dest, const GstBuffer * src);
G_END_DECLS

View file

@ -100,7 +100,7 @@ typedef struct
CothreadPrivate;
#define ELEMENT_PRIVATE(element) ((CothreadPrivate *) GST_ELEMENT (element)->sched_private)
#define SCHED(element) (GST_ENTRY_SCHEDULER ((element)->sched))
#define SCHED(element) (GST_ENTRY_SCHEDULER ((element)->scheduler))
typedef struct
{

View file

@ -647,7 +647,7 @@ gst_basic_scheduler_cothreaded_chain (GstBin * bin, GstSchedulerChain * chain)
if (peerpad) {
GstElement *peerelement = GST_ELEMENT (GST_PAD_PARENT (peerpad));
gboolean different_sched =
(peerelement->sched != GST_SCHEDULER (chain->sched));
(peerelement->scheduler != GST_SCHEDULER (chain->sched));
gboolean peer_decoupled =
GST_FLAG_IS_SET (peerelement, GST_ELEMENT_DECOUPLED);
@ -804,7 +804,7 @@ gst_basic_scheduler_chain_add_element (GstSchedulerChain * chain,
GstElement * element)
{
/* set the sched pointer for the element */
element->sched = GST_SCHEDULER (chain->sched);
element->scheduler = GST_SCHEDULER (chain->sched);
/* add the element to either the main list or the disabled list */
if (GST_STATE (element) == GST_STATE_PLAYING) {

View file

@ -19,10 +19,12 @@ install-pluginLTLIBRARIES:
CLEANFILES = core.*
TESTS = $(top_builddir)/tools/gst-register-@GST_MAJORMINOR@ \
gst/gstcaps \
gst/gstdata \
gst/gstiterator \
gst/gstobject \
gst/gstbin \
gst/gstcaps \
gst/gstdata \
gst/gstiterator \
gst/gstobject \
gst/gstsystemclock \
gst-libs/gdp
check_PROGRAMS = $(TESTS)

110
tests/check/gst/gstbin.c Normal file
View file

@ -0,0 +1,110 @@
/* GStreamer
* Copyright (C) 2005 Wim Taymans <wim@fluendo.com>
*
* gstbin.c: Unit test for GstBin
*
* 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 "../gstcheck.h"
START_TEST (test_interface)
{
GstBin *bin, *bin2;
GstElement *filesrc;
GstIterator *it;
gpointer item;
bin = GST_BIN (gst_bin_new (NULL));
fail_unless (bin != NULL, "Could not create bin");
filesrc = gst_element_factory_make ("filesrc", NULL);
fail_unless (filesrc != NULL, "Could not create filesrc");
fail_unless (GST_IS_URI_HANDLER (filesrc), "Filesrc not a URI handler");
gst_bin_add (bin, filesrc);
fail_unless (gst_bin_get_by_interface (bin, GST_TYPE_URI_HANDLER) == filesrc);
it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER);
fail_unless (it != NULL);
fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
fail_unless (item == (gpointer) filesrc);
fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
gst_iterator_free (it);
gst_bin_add_many (bin,
gst_element_factory_make ("identity", NULL),
gst_element_factory_make ("identity", NULL),
gst_element_factory_make ("identity", NULL), NULL);
fail_unless (gst_bin_get_by_interface (bin, GST_TYPE_URI_HANDLER) == filesrc);
it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER);
fail_unless (it != NULL);
fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
fail_unless (item == (gpointer) filesrc);
fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
gst_iterator_free (it);
bin2 = bin;
bin = GST_BIN (gst_bin_new (NULL));
fail_unless (bin != NULL);
gst_bin_add_many (bin,
gst_element_factory_make ("identity", NULL),
gst_element_factory_make ("identity", NULL),
GST_ELEMENT (bin2), gst_element_factory_make ("identity", NULL), NULL);
fail_unless (gst_bin_get_by_interface (bin, GST_TYPE_URI_HANDLER) == filesrc);
it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER);
fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
fail_unless (item == (gpointer) filesrc);
fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
gst_iterator_free (it);
gst_bin_add (bin, gst_element_factory_make ("filesrc", NULL));
gst_bin_add (bin2, gst_element_factory_make ("filesrc", NULL));
it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER);
fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
fail_unless (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
gst_iterator_free (it);
g_object_unref (bin);
}
END_TEST Suite * gst_bin_suite (void)
{
Suite *s = suite_create ("GstBin");
TCase *tc_chain = tcase_create ("bin tests");
suite_add_tcase (s, tc_chain);
tcase_add_test (tc_chain, test_interface);
return s;
}
int
main (int argc, char **argv)
{
int nf;
Suite *s = gst_bin_suite ();
SRunner *sr = srunner_create (s);
gst_check_init (&argc, &argv);
srunner_run_all (sr, CK_NORMAL);
nf = srunner_ntests_failed (sr);
srunner_free (sr);
return nf;
}

View file

@ -0,0 +1,221 @@
/* GStreamer
* Copyright (C) 2005 Wim Taymans <wim@fluendo.com>
*
* gstsystemclock.c: Unit test for GstSystemClock
*
* 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 "../gstcheck.h"
START_TEST (test_signedness)
{
GstClockTime time[] = { 0, 1, G_MAXUINT64 / GST_SECOND };
GstClockTimeDiff diff[] =
{ 0, 1, -1, G_MAXINT64 / GST_SECOND, G_MININT64 / GST_SECOND };
guint i;
for (i = 0; i < G_N_ELEMENTS (time); i++) {
fail_if (time[i] != (time[i] * GST_SECOND / GST_SECOND));
}
for (i = 0; i < G_N_ELEMENTS (diff); i++) {
fail_if (diff[i] != (diff[i] * GST_SECOND / GST_SECOND));
}
}
END_TEST
#define TIME_UNIT GST_SECOND
static void
gst_clock_debug (GstClock * clock)
{
GstClockTime time;
time = gst_clock_get_time (clock);
g_message ("Clock info: time %" G_GUINT64_FORMAT "\n", time);
}
static gboolean
ok_callback (GstClock * clock, GstClockTime time,
GstClockID id, gpointer user_data)
{
g_message ("unlocked async id %p\n", id);
return FALSE;
}
static gboolean
error_callback (GstClock * clock, GstClockTime time,
GstClockID id, gpointer user_data)
{
g_message ("unlocked unscheduled async id %p, this is wrong\n", id);
fail_if (TRUE);
return FALSE;
}
START_TEST (test_single_shot)
{
GstClock *clock;
GstClockID id, id2;
GstClockTime base;
GstClockReturn result;
clock = gst_system_clock_obtain ();
fail_unless (clock != NULL, "Could not create instance of GstSystemClock");
gst_clock_debug (clock);
base = gst_clock_get_time (clock);
id = gst_clock_new_single_shot_id (clock, base + TIME_UNIT);
fail_unless (id != NULL, "Could not create single shot id");
g_message ("waiting one second\n");
result = gst_clock_id_wait (id, NULL);
gst_clock_debug (clock);
fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
g_message ("waiting in the past\n");
result = gst_clock_id_wait (id, NULL);
gst_clock_debug (clock);
fail_unless (result == GST_CLOCK_EARLY, "Waiting did not return EARLY");
gst_clock_id_unref (id);
id = gst_clock_new_single_shot_id (clock, base + 2 * TIME_UNIT);
g_message ("waiting one second async id %p\n", id);
result = gst_clock_id_wait_async (id, ok_callback, NULL);
gst_clock_id_unref (id);
fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
g_usleep (2 * G_USEC_PER_SEC);
id = gst_clock_new_single_shot_id (clock, base + 5 * TIME_UNIT);
g_message ("waiting one second async, with cancel on id %p\n", id);
result = gst_clock_id_wait_async (id, error_callback, NULL);
fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
g_usleep (G_USEC_PER_SEC / 2);
g_message ("cancel id %p after 0.5 seconds\n", id);
gst_clock_id_unschedule (id);
gst_clock_id_unref (id);
g_message ("canceled id %p\n", id);
g_message ("waiting multiple one second async, with cancel\n");
id = gst_clock_new_single_shot_id (clock, base + 5 * TIME_UNIT);
id2 = gst_clock_new_single_shot_id (clock, base + 6 * TIME_UNIT);
g_message ("waiting id %p\n", id);
result = gst_clock_id_wait_async (id, ok_callback, NULL);
fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
gst_clock_id_unref (id);
g_message ("waiting id %p\n", id2);
result = gst_clock_id_wait_async (id2, error_callback, NULL);
fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
g_usleep (G_USEC_PER_SEC / 2);
g_message ("cancel id %p after 0.5 seconds\n", id2);
gst_clock_id_unschedule (id2);
g_message ("canceled id %p\n", id2);
gst_clock_id_unref (id2);
g_usleep (2 * G_USEC_PER_SEC);
}
END_TEST
START_TEST (test_periodic_shot)
{
GstClock *clock;
GstClockID id, id2;
GstClockTime base;
GstClockReturn result;
clock = gst_system_clock_obtain ();
fail_unless (clock != NULL, "Could not create instance of GstSystemClock");
gst_clock_debug (clock);
base = gst_clock_get_time (clock);
/* signal every half a second */
id = gst_clock_new_periodic_id (clock, base + TIME_UNIT, TIME_UNIT / 2);
fail_unless (id != NULL, "Could not create periodic id");
g_message ("waiting one second\n");
result = gst_clock_id_wait (id, NULL);
gst_clock_debug (clock);
fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
g_message ("waiting for the next\n");
result = gst_clock_id_wait (id, NULL);
gst_clock_debug (clock);
fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
g_message ("waiting for the next async %p\n", id);
result = gst_clock_id_wait_async (id, ok_callback, NULL);
fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
g_usleep (2 * G_USEC_PER_SEC);
g_message ("waiting some more for the next async %p\n", id);
result = gst_clock_id_wait_async (id, ok_callback, NULL);
fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
g_usleep (2 * G_USEC_PER_SEC);
id2 = gst_clock_new_periodic_id (clock, base + TIME_UNIT, TIME_UNIT / 2);
fail_unless (id2 != NULL, "Could not create second periodic id");
g_message ("waiting some more for another async %p\n", id2);
result = gst_clock_id_wait_async (id2, ok_callback, NULL);
fail_unless (result == GST_CLOCK_OK, "Waiting did not return OK");
g_usleep (2 * G_USEC_PER_SEC);
g_message ("unschedule %p\n", id);
gst_clock_id_unschedule (id);
/* entry cannot be used again */
result = gst_clock_id_wait_async (id, error_callback, NULL);
fail_unless (result == GST_CLOCK_UNSCHEDULED,
"Waiting did not return UNSCHEDULED");
result = gst_clock_id_wait (id, NULL);
fail_unless (result == GST_CLOCK_UNSCHEDULED,
"Waiting did not return UNSCHEDULED");
g_usleep (2 * G_USEC_PER_SEC);
}
END_TEST Suite * gst_systemclock_suite (void)
{
Suite *s = suite_create ("GstSystemClock");
TCase *tc_chain = tcase_create ("waiting");
/* increase timeout */
tcase_set_timeout (tc_chain, 20);
suite_add_tcase (s, tc_chain);
tcase_add_test (tc_chain, test_signedness);
tcase_add_test (tc_chain, test_single_shot);
tcase_add_test (tc_chain, test_periodic_shot);
return s;
}
int
main (int argc, char **argv)
{
int nf;
Suite *s = gst_systemclock_suite ();
SRunner *sr = srunner_create (s);
gst_check_init (&argc, &argv);
srunner_run_all (sr, CK_NORMAL);
nf = srunner_ntests_failed (sr);
srunner_free (sr);
return nf;
}

View file

@ -25,8 +25,9 @@ gint
main (gint argc, gchar * argv[])
{
GstBin *bin, *bin2;
GList *list;
GstElement *filesrc;
GstIterator *it;
gpointer item;
gst_init (&argc, &argv);
@ -39,20 +40,24 @@ main (gint argc, gchar * argv[])
gst_bin_add (bin, filesrc);
g_assert (gst_bin_get_by_interface (bin, GST_TYPE_URI_HANDLER) == filesrc);
list = gst_bin_get_all_by_interface (bin, GST_TYPE_URI_HANDLER);
g_assert (g_list_length (list) == 1);
g_assert (list->data == (gpointer) filesrc);
g_list_free (list);
it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER);
g_assert (it != NULL);
g_assert (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
g_assert (item == (gpointer) filesrc);
g_assert (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
gst_iterator_free (it);
gst_bin_add_many (bin,
gst_element_factory_make ("identity", NULL),
gst_element_factory_make ("identity", NULL),
gst_element_factory_make ("identity", NULL), NULL);
g_assert (gst_bin_get_by_interface (bin, GST_TYPE_URI_HANDLER) == filesrc);
list = gst_bin_get_all_by_interface (bin, GST_TYPE_URI_HANDLER);
g_assert (g_list_length (list) == 1);
g_assert (list->data == (gpointer) filesrc);
g_list_free (list);
it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER);
g_assert (it != NULL);
g_assert (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
g_assert (item == (gpointer) filesrc);
g_assert (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
gst_iterator_free (it);
bin2 = bin;
bin = GST_BIN (gst_bin_new (NULL));
@ -62,16 +67,20 @@ main (gint argc, gchar * argv[])
gst_element_factory_make ("identity", NULL),
GST_ELEMENT (bin2), gst_element_factory_make ("identity", NULL), NULL);
g_assert (gst_bin_get_by_interface (bin, GST_TYPE_URI_HANDLER) == filesrc);
list = gst_bin_get_all_by_interface (bin, GST_TYPE_URI_HANDLER);
g_assert (g_list_length (list) == 1);
g_assert (list->data == (gpointer) filesrc);
g_list_free (list);
it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER);
g_assert (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
g_assert (item == (gpointer) filesrc);
g_assert (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
gst_iterator_free (it);
gst_bin_add (bin, gst_element_factory_make ("filesrc", NULL));
gst_bin_add (bin2, gst_element_factory_make ("filesrc", NULL));
list = gst_bin_get_all_by_interface (bin, GST_TYPE_URI_HANDLER);
g_assert (g_list_length (list) == 3);
g_list_free (list);
it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER);
g_assert (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
g_assert (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
g_assert (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
g_assert (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
gst_iterator_free (it);
g_object_unref (bin);
return 0;

View file

@ -25,8 +25,9 @@ gint
main (gint argc, gchar * argv[])
{
GstBin *bin, *bin2;
GList *list;
GstElement *filesrc;
GstIterator *it;
gpointer item;
gst_init (&argc, &argv);
@ -39,20 +40,24 @@ main (gint argc, gchar * argv[])
gst_bin_add (bin, filesrc);
g_assert (gst_bin_get_by_interface (bin, GST_TYPE_URI_HANDLER) == filesrc);
list = gst_bin_get_all_by_interface (bin, GST_TYPE_URI_HANDLER);
g_assert (g_list_length (list) == 1);
g_assert (list->data == (gpointer) filesrc);
g_list_free (list);
it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER);
g_assert (it != NULL);
g_assert (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
g_assert (item == (gpointer) filesrc);
g_assert (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
gst_iterator_free (it);
gst_bin_add_many (bin,
gst_element_factory_make ("identity", NULL),
gst_element_factory_make ("identity", NULL),
gst_element_factory_make ("identity", NULL), NULL);
g_assert (gst_bin_get_by_interface (bin, GST_TYPE_URI_HANDLER) == filesrc);
list = gst_bin_get_all_by_interface (bin, GST_TYPE_URI_HANDLER);
g_assert (g_list_length (list) == 1);
g_assert (list->data == (gpointer) filesrc);
g_list_free (list);
it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER);
g_assert (it != NULL);
g_assert (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
g_assert (item == (gpointer) filesrc);
g_assert (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
gst_iterator_free (it);
bin2 = bin;
bin = GST_BIN (gst_bin_new (NULL));
@ -62,16 +67,20 @@ main (gint argc, gchar * argv[])
gst_element_factory_make ("identity", NULL),
GST_ELEMENT (bin2), gst_element_factory_make ("identity", NULL), NULL);
g_assert (gst_bin_get_by_interface (bin, GST_TYPE_URI_HANDLER) == filesrc);
list = gst_bin_get_all_by_interface (bin, GST_TYPE_URI_HANDLER);
g_assert (g_list_length (list) == 1);
g_assert (list->data == (gpointer) filesrc);
g_list_free (list);
it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER);
g_assert (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
g_assert (item == (gpointer) filesrc);
g_assert (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
gst_iterator_free (it);
gst_bin_add (bin, gst_element_factory_make ("filesrc", NULL));
gst_bin_add (bin2, gst_element_factory_make ("filesrc", NULL));
list = gst_bin_get_all_by_interface (bin, GST_TYPE_URI_HANDLER);
g_assert (g_list_length (list) == 3);
g_list_free (list);
it = gst_bin_iterate_all_by_interface (bin, GST_TYPE_URI_HANDLER);
g_assert (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
g_assert (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
g_assert (gst_iterator_next (it, &item) == GST_ITERATOR_OK);
g_assert (gst_iterator_next (it, &item) == GST_ITERATOR_DONE);
gst_iterator_free (it);
g_object_unref (bin);
return 0;