gst/gstbin.c: don't

Original commit message from CVS:
* gst/gstbin.c: (gst_bin_iterate_func), (gst_bin_iterate):
don't
* gst/schedulers/entryscheduler.c: (safe_cothread_switch),
(safe_cothread_destroy),
(gst_entry_scheduler_remove_all_cothreads),
(gst_entry_scheduler_reset), (_remove_cothread),
(gst_entry_scheduler_state_transition):
hold off cothread destruction if we're not in main cothread
* configure.ac:
* testsuite/Makefile.am:
add new test dir
* testsuite/schedulers/.cvsignore:
* testsuite/schedulers/Makefile.am:
add tests
* testsuite/schedulers/relink.c: (cb_handoff), (main):
check relinking and adding/removing elements from a running pipeline
* testsuite/schedulers/unlink.c: (cb_handoff), (main):
check unlinking in a running pipeline
* testsuite/schedulers/unref.c: (cb_handoff), (main):
check unreffing a running pipeline
* testsuite/schedulers/useless_iteration.c: (main):
check iterating a pipeline that contains running threads works
This commit is contained in:
Benjamin Otte 2004-05-18 21:18:43 +00:00
parent 237bc63426
commit 05c2afa7f9
18 changed files with 681 additions and 56 deletions

View file

@ -1,3 +1,28 @@
2004-05-18 Benjamin Otte <in7y118@public.uni-hamburg.de>
* gst/gstbin.c: (gst_bin_iterate_func), (gst_bin_iterate):
don't
* gst/schedulers/entryscheduler.c: (safe_cothread_switch),
(safe_cothread_destroy),
(gst_entry_scheduler_remove_all_cothreads),
(gst_entry_scheduler_reset), (_remove_cothread),
(gst_entry_scheduler_state_transition):
hold off cothread destruction if we're not in main cothread
* configure.ac:
* testsuite/Makefile.am:
add new test dir
* testsuite/schedulers/.cvsignore:
* testsuite/schedulers/Makefile.am:
add tests
* testsuite/schedulers/relink.c: (cb_handoff), (main):
check relinking and adding/removing elements from a running pipeline
* testsuite/schedulers/unlink.c: (cb_handoff), (main):
check unlinking in a running pipeline
* testsuite/schedulers/unref.c: (cb_handoff), (main):
check unreffing a running pipeline
* testsuite/schedulers/useless_iteration.c: (main):
check iterating a pipeline that contains running threads works
2004-05-18 David Schleef <ds@schleef.org>
* docs/gst/Makefile.am: Add all-local target for when HAVE_GTK_DOC

View file

@ -670,6 +670,7 @@ testsuite/negotiation/Makefile
testsuite/parse/Makefile
testsuite/plugin/Makefile
testsuite/refcounting/Makefile
testsuite/schedulers/Makefile
testsuite/tags/Makefile
testsuite/threads/Makefile
examples/Makefile

View file

@ -1112,17 +1112,35 @@ gst_bin_restore_thyself (GstObject * object, xmlNodePtr self)
static gboolean
gst_bin_iterate_func (GstBin * bin)
{
GstScheduler *sched = GST_ELEMENT_SCHED (bin);
/* only iterate if this is the manager bin */
if (GST_ELEMENT_SCHED (bin) &&
GST_ELEMENT_SCHED (bin)->parent == GST_ELEMENT (bin)) {
if (sched && sched->parent == GST_ELEMENT (bin)) {
GstSchedulerState state;
state = gst_scheduler_iterate (GST_ELEMENT_SCHED (bin));
state = gst_scheduler_iterate (sched);
if (state == GST_SCHEDULER_STATE_RUNNING) {
return TRUE;
} else if (state == GST_SCHEDULER_STATE_ERROR) {
gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PAUSED);
} else if (state == GST_SCHEDULER_STATE_STOPPED) {
/* check if we have children scheds that are still running */
/* FIXME: remove in 0.9? autouseless because iterations gone? */
GList *walk;
for (walk = sched->schedulers; walk; walk = g_list_next (walk)) {
GstScheduler *test = walk->data;
g_return_val_if_fail (test->parent, FALSE);
if (GST_STATE (test->parent) == GST_STATE_PLAYING) {
GST_CAT_DEBUG_OBJECT (GST_CAT_SCHEDULING, bin,
"current bin is not iterating, but children are, "
"so returning TRUE anyway...");
g_usleep (1);
return TRUE;
}
}
}
} else {
g_warning ("bin \"%s\" is not the managing bin, can't be iterated on!\n",
@ -1150,25 +1168,13 @@ gst_bin_iterate (GstBin * bin)
g_return_val_if_fail (GST_IS_BIN (bin), FALSE);
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, bin, "starting iteration");
gst_object_ref (GST_OBJECT (bin));
running = FALSE;
g_signal_emit (G_OBJECT (bin), gst_bin_signals[ITERATE], 0, &running);
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, bin, "finished iteration");
if (!running) {
if (GST_STATE (bin) == GST_STATE_PLAYING &&
GST_STATE_PENDING (bin) == GST_STATE_VOID_PENDING) {
GST_CAT_DEBUG (GST_CAT_SCHEDULING,
"[%s]: polling for child shutdown after useless iteration",
GST_ELEMENT_NAME (bin));
g_usleep (1);
running = TRUE;
}
}
gst_object_unref (GST_OBJECT (bin));
GST_CAT_LOG_OBJECT (GST_CAT_SCHEDULING, bin, "finished iteration");
return running;
}

View file

@ -130,6 +130,8 @@ struct _GstEntryScheduler
GList *schedule_possible; /* possible entry points */
GList *waiting; /* elements waiting for the clock */
gboolean error; /* if an element threw an error */
GSList *reaping; /* cothreads we need to destroy but can't */
};
struct _GstEntrySchedulerClass
@ -526,10 +528,37 @@ can_schedule (Entry * entry)
}
}
#define safe_cothread_switch(sched,cothread) G_STMT_START{ \
if (do_cothread_get_current (sched->context) != cothread) \
do_cothread_switch (cothread); \
}G_STMT_END
static void
safe_cothread_switch (GstEntryScheduler * scheduler, cothread * thread)
{
GList *list;
cothread *cur = do_cothread_get_current (scheduler->context);
if (cur == thread) {
GST_LOG_OBJECT (scheduler, "switch to same cothread, ignoring");
}
for (list = scheduler->schedule_possible; list; list = g_list_next (list)) {
if (ENTRY_IS_COTHREAD (list->data)) {
CothreadPrivate *priv = (CothreadPrivate *) list->data;
if (priv->thread == thread)
gst_object_ref (GST_OBJECT (priv->element));
if (priv->thread == cur)
gst_object_unref (GST_OBJECT (priv->element));
}
}
do_cothread_switch (thread);
if (cur == do_cothread_get_main (scheduler->context)) {
GSList *walk;
for (walk = scheduler->reaping; walk; walk = g_slist_next (walk)) {
do_cothread_destroy (walk->data);
}
g_slist_free (scheduler->reaping);
scheduler->reaping = NULL;
}
}
/* the meat - no guarantee as to which cothread this function is called */
static void
@ -738,27 +767,47 @@ gst_entry_scheduler_setup (GstScheduler * sched)
}
}
static void
safe_cothread_destroy (CothreadPrivate * thread)
{
GstEntryScheduler *scheduler = thread->sched;
if (do_cothread_get_current (scheduler->context) ==
do_cothread_get_main (scheduler->context)) {
do_cothread_destroy (thread->thread);
} else {
GST_WARNING_OBJECT (scheduler, "delaying destruction of cothread %p",
thread->thread);
scheduler->reaping = g_slist_prepend (scheduler->reaping, thread->thread);
}
thread->thread = NULL;
}
static void
gst_entry_scheduler_remove_all_cothreads (GstEntryScheduler * scheduler)
{
GList *list;
for (list = scheduler->schedule_possible; list; list = g_list_next (list)) {
if (ENTRY_IS_COTHREAD (list->data)) {
CothreadPrivate *priv = (CothreadPrivate *) list->data;
if (priv->thread)
safe_cothread_destroy (priv);
}
}
}
static void
gst_entry_scheduler_reset (GstScheduler * sched)
{
#if 0
/* FIXME: do we need to destroy cothreads ourselves? */
GList *elements = GST_ENTRY_SCHEDULER (sched)->elements;
GstEntryScheduler *scheduler = GST_ENTRY_SCHEDULER (sched);
while (elements) {
GstElement *element = GST_ELEMENT (elements->data);
if (GST_ELEMENT_THREADSTATE (element)) {
do_cothread_destroy (GST_ELEMENT_THREADSTATE (element));
GST_ELEMENT_THREADSTATE (element) = NULL;
}
elements = g_list_next (elements);
}
#endif
if (GST_ENTRY_SCHEDULER (sched)->context) {
do_cothread_context_destroy (GST_ENTRY_SCHEDULER (sched)->context);
GST_ENTRY_SCHEDULER (sched)->context = NULL;
if (scheduler->context) {
g_return_if_fail (scheduler->reaping == NULL);
gst_entry_scheduler_remove_all_cothreads (scheduler);
do_cothread_context_destroy (scheduler->context);
scheduler->context = NULL;
}
}
@ -813,7 +862,7 @@ _remove_cothread (CothreadPrivate * priv)
sched->schedule_possible = g_list_remove (sched->schedule_possible, priv);
if (priv->thread)
do_cothread_destroy (priv->thread);
safe_cothread_destroy (priv);
g_free (priv);
}
@ -856,23 +905,11 @@ gst_entry_scheduler_state_transition (GstScheduler * scheduler,
break;
case GST_STATE_PAUSED_TO_READY:
if (element == scheduler->parent) {
GList *list;
for (list = sched->schedule_possible; list; list = g_list_next (list)) {
if (ENTRY_IS_COTHREAD (list->data)) {
CothreadPrivate *priv = (CothreadPrivate *) list->data;
if (priv->thread) {
do_cothread_destroy (priv->thread);
priv->thread = NULL;
}
}
}
gst_entry_scheduler_remove_all_cothreads (sched);
}
if (element->sched_private != NULL
&& ELEMENT_PRIVATE (element)->thread != NULL) {
do_cothread_destroy (ELEMENT_PRIVATE (element)->thread);
ELEMENT_PRIVATE (element)->thread = NULL;
safe_cothread_destroy (ELEMENT_PRIVATE (element));
}
break;
case GST_STATE_READY_TO_NULL:

View file

@ -16,11 +16,11 @@ endif
SUBDIRS = bins bytestream cleanup dynparams ghostpads \
caps plugin elements clock refcounting tags threads \
indexers debug $(GST_PARSE_DIRS) $(GST_DEBUG_DIRS) \
dlopen negotiation
dlopen negotiation schedulers
DIST_SUBDIRS = bins bytestream caps cleanup clock dynparams elements indexers \
plugin refcounting tags threads parse debug ghostpads \
dlopen negotiation
dlopen negotiation schedulers
tests_pass = test_gst_init
tests_fail =

View file

@ -0,0 +1,7 @@
relink_sink
relink_src
unlink_sink
unlink_src
unref_sink
unref_src
useless_iteration

View file

@ -0,0 +1,23 @@
include ../Rules
tests_pass = \
unlink_src unlink_sink \
relink_src relink_sink \
unref_src unref_sink \
useless_iteration
tests_fail =
tests_ignore =
unlink_src_SOURCES = unlink.c
unlink_src_CFLAGS = $(AM_CFLAGS) -DELEMENT=src
unlink_sink_SOURCES = unlink.c
unlink_sink_CFLAGS = $(AM_CFLAGS) -DELEMENT=sink
relink_src_SOURCES = relink.c
relink_src_CFLAGS = $(AM_CFLAGS) -DELEMENT=src -DOTHER_ELEMENT=sink
relink_sink_SOURCES = relink.c
relink_sink_CFLAGS = $(AM_CFLAGS) -DELEMENT=sink -DOTHER_ELEMENT=src
unref_src_SOURCES = unref.c
unref_src_CFLAGS = $(AM_CFLAGS) -DELEMENT=src
unref_sink_SOURCES = unref.c
unref_sink_CFLAGS = $(AM_CFLAGS) -DELEMENT=sink

View file

@ -0,0 +1,73 @@
/* GStreamer
* Copyright (C) 2004 Benjamin Otte <in7y118@public.uni-hamburg.de>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <gst/gst.h>
GstElement *pipeline, *src, *sink;
static void
cb_handoff (GstElement * element, GstBuffer * buffer, GstPad * pad,
gpointer unused)
{
if (GST_PAD_PEER (pad)) {
g_print ("relinking...\n");
gst_pad_unlink (pad, GST_PAD_PEER (pad));
gst_bin_remove (GST_BIN (pipeline), OTHER_ELEMENT);
OTHER_ELEMENT =
gst_element_factory_make ("fake" G_STRINGIFY (OTHER_ELEMENT), NULL);
g_assert (OTHER_ELEMENT);
gst_bin_add (GST_BIN (pipeline), OTHER_ELEMENT);
gst_element_sync_state_with_parent (OTHER_ELEMENT);
gst_element_link (ELEMENT, OTHER_ELEMENT);
}
}
gint
main (gint argc, gchar ** argv)
{
guint i = 0;
gst_init (&argc, &argv);
g_print ("setting up...\n");
/* setup pipeline */
pipeline = gst_element_factory_make ("pipeline", NULL);
g_assert (pipeline);
src = gst_element_factory_make ("fakesrc", NULL);
g_assert (src);
sink = gst_element_factory_make ("fakesink", NULL);
g_assert (sink);
gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL);
gst_element_link (src, sink);
/* setup special stuff */
g_object_set (ELEMENT, "signal-handoffs", TRUE, NULL);
g_signal_connect (ELEMENT, "handoff", (GCallback) cb_handoff, NULL);
/* run pipeline */
g_print ("running...\n");
if (gst_element_set_state (pipeline, GST_STATE_PLAYING) != GST_STATE_SUCCESS)
g_assert_not_reached ();
while (i++ < 10 && gst_bin_iterate (GST_BIN (pipeline)));
g_print ("cleaning up...\n");
gst_object_unref (GST_OBJECT (pipeline));
pipeline = NULL;
g_print ("done.\n");
return 0;
}

View file

@ -0,0 +1,64 @@
/* GStreamer
* Copyright (C) 2004 Benjamin Otte <in7y118@public.uni-hamburg.de>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <gst/gst.h>
static void
cb_handoff (GstElement * element, GstBuffer * buffer, GstPad * pad,
gpointer unused)
{
if (GST_PAD_PEER (pad)) {
g_print ("unlinking...\n");
gst_pad_unlink (pad, GST_PAD_PEER (pad));
}
}
gint
main (gint argc, gchar ** argv)
{
GstElement *pipeline, *src, *sink;
gst_init (&argc, &argv);
g_print ("setting up...\n");
/* setup pipeline */
pipeline = gst_element_factory_make ("pipeline", NULL);
g_assert (pipeline);
src = gst_element_factory_make ("fakesrc", NULL);
g_assert (src);
sink = gst_element_factory_make ("fakesink", NULL);
g_assert (sink);
gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL);
gst_element_link (src, sink);
/* setup special stuff */
g_object_set (ELEMENT, "signal-handoffs", TRUE, NULL);
g_signal_connect (ELEMENT, "handoff", (GCallback) cb_handoff, NULL);
/* run pipeline */
g_print ("running...\n");
if (gst_element_set_state (pipeline, GST_STATE_PLAYING) != GST_STATE_SUCCESS)
g_assert_not_reached ();
while (gst_bin_iterate (GST_BIN (pipeline)));
g_print ("cleaning up...\n");
gst_object_unref (GST_OBJECT (pipeline));
pipeline = NULL;
g_print ("done.\n");
return 0;
}

View file

@ -0,0 +1,61 @@
/* GStreamer
* Copyright (C) 2004 Benjamin Otte <in7y118@public.uni-hamburg.de>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <gst/gst.h>
GstElement *pipeline, *src, *sink;
static void
cb_handoff (GstElement * element, GstBuffer * buffer, GstPad * pad,
gpointer unused)
{
if (pipeline) {
g_print ("unreffing...\n");
gst_object_unref (GST_OBJECT (pipeline));
pipeline = NULL;
}
}
gint
main (gint argc, gchar ** argv)
{
gst_init (&argc, &argv);
g_print ("setting up...\n");
/* setup pipeline */
pipeline = gst_element_factory_make ("pipeline", NULL);
g_assert (pipeline);
src = gst_element_factory_make ("fakesrc", NULL);
g_assert (src);
sink = gst_element_factory_make ("fakesink", NULL);
g_assert (sink);
gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL);
gst_element_link (src, sink);
/* setup special stuff */
g_object_set (ELEMENT, "signal-handoffs", TRUE, NULL);
g_signal_connect (ELEMENT, "handoff", (GCallback) cb_handoff, NULL);
/* run pipeline */
g_print ("running...\n");
if (gst_element_set_state (pipeline, GST_STATE_PLAYING) != GST_STATE_SUCCESS)
g_assert_not_reached ();
while (pipeline && gst_bin_iterate (GST_BIN (pipeline)));
g_print ("done.\n");
return 0;
}

View file

@ -0,0 +1,50 @@
/* GStreamer
* Copyright (C) 2004 Benjamin Otte <in7y118@public.uni-hamburg.de>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <gst/gst.h>
gint
main (gint argc, gchar ** argv)
{
GstElement *pipeline;
GError *error = NULL;
guint i = 0;
gst_init (&argc, &argv);
g_print ("setting up...\n");
/* setup pipeline */
pipeline = gst_parse_launch ("pipeline.( { fakesrc ! fakesink } )", &error);
g_assert (error == NULL);
g_assert (pipeline);
/* run pipeline */
g_print ("running...\n");
if (gst_element_set_state (pipeline, GST_STATE_PLAYING) != GST_STATE_SUCCESS)
g_assert_not_reached ();
while (i < 100 && gst_bin_iterate (GST_BIN (pipeline)))
i++;
g_print ("cleaning up... (%d iterations)\n", i);
g_assert (i == 100);
gst_object_unref (GST_OBJECT (pipeline));
pipeline = NULL;
g_print ("done.\n");
return 0;
}

View file

@ -16,11 +16,11 @@ endif
SUBDIRS = bins bytestream cleanup dynparams ghostpads \
caps plugin elements clock refcounting tags threads \
indexers debug $(GST_PARSE_DIRS) $(GST_DEBUG_DIRS) \
dlopen negotiation
dlopen negotiation schedulers
DIST_SUBDIRS = bins bytestream caps cleanup clock dynparams elements indexers \
plugin refcounting tags threads parse debug ghostpads \
dlopen negotiation
dlopen negotiation schedulers
tests_pass = test_gst_init
tests_fail =

7
testsuite/schedulers/.gitignore vendored Normal file
View file

@ -0,0 +1,7 @@
relink_sink
relink_src
unlink_sink
unlink_src
unref_sink
unref_src
useless_iteration

View file

@ -0,0 +1,23 @@
include ../Rules
tests_pass = \
unlink_src unlink_sink \
relink_src relink_sink \
unref_src unref_sink \
useless_iteration
tests_fail =
tests_ignore =
unlink_src_SOURCES = unlink.c
unlink_src_CFLAGS = $(AM_CFLAGS) -DELEMENT=src
unlink_sink_SOURCES = unlink.c
unlink_sink_CFLAGS = $(AM_CFLAGS) -DELEMENT=sink
relink_src_SOURCES = relink.c
relink_src_CFLAGS = $(AM_CFLAGS) -DELEMENT=src -DOTHER_ELEMENT=sink
relink_sink_SOURCES = relink.c
relink_sink_CFLAGS = $(AM_CFLAGS) -DELEMENT=sink -DOTHER_ELEMENT=src
unref_src_SOURCES = unref.c
unref_src_CFLAGS = $(AM_CFLAGS) -DELEMENT=src
unref_sink_SOURCES = unref.c
unref_sink_CFLAGS = $(AM_CFLAGS) -DELEMENT=sink

View file

@ -0,0 +1,73 @@
/* GStreamer
* Copyright (C) 2004 Benjamin Otte <in7y118@public.uni-hamburg.de>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <gst/gst.h>
GstElement *pipeline, *src, *sink;
static void
cb_handoff (GstElement * element, GstBuffer * buffer, GstPad * pad,
gpointer unused)
{
if (GST_PAD_PEER (pad)) {
g_print ("relinking...\n");
gst_pad_unlink (pad, GST_PAD_PEER (pad));
gst_bin_remove (GST_BIN (pipeline), OTHER_ELEMENT);
OTHER_ELEMENT =
gst_element_factory_make ("fake" G_STRINGIFY (OTHER_ELEMENT), NULL);
g_assert (OTHER_ELEMENT);
gst_bin_add (GST_BIN (pipeline), OTHER_ELEMENT);
gst_element_sync_state_with_parent (OTHER_ELEMENT);
gst_element_link (ELEMENT, OTHER_ELEMENT);
}
}
gint
main (gint argc, gchar ** argv)
{
guint i = 0;
gst_init (&argc, &argv);
g_print ("setting up...\n");
/* setup pipeline */
pipeline = gst_element_factory_make ("pipeline", NULL);
g_assert (pipeline);
src = gst_element_factory_make ("fakesrc", NULL);
g_assert (src);
sink = gst_element_factory_make ("fakesink", NULL);
g_assert (sink);
gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL);
gst_element_link (src, sink);
/* setup special stuff */
g_object_set (ELEMENT, "signal-handoffs", TRUE, NULL);
g_signal_connect (ELEMENT, "handoff", (GCallback) cb_handoff, NULL);
/* run pipeline */
g_print ("running...\n");
if (gst_element_set_state (pipeline, GST_STATE_PLAYING) != GST_STATE_SUCCESS)
g_assert_not_reached ();
while (i++ < 10 && gst_bin_iterate (GST_BIN (pipeline)));
g_print ("cleaning up...\n");
gst_object_unref (GST_OBJECT (pipeline));
pipeline = NULL;
g_print ("done.\n");
return 0;
}

View file

@ -0,0 +1,64 @@
/* GStreamer
* Copyright (C) 2004 Benjamin Otte <in7y118@public.uni-hamburg.de>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <gst/gst.h>
static void
cb_handoff (GstElement * element, GstBuffer * buffer, GstPad * pad,
gpointer unused)
{
if (GST_PAD_PEER (pad)) {
g_print ("unlinking...\n");
gst_pad_unlink (pad, GST_PAD_PEER (pad));
}
}
gint
main (gint argc, gchar ** argv)
{
GstElement *pipeline, *src, *sink;
gst_init (&argc, &argv);
g_print ("setting up...\n");
/* setup pipeline */
pipeline = gst_element_factory_make ("pipeline", NULL);
g_assert (pipeline);
src = gst_element_factory_make ("fakesrc", NULL);
g_assert (src);
sink = gst_element_factory_make ("fakesink", NULL);
g_assert (sink);
gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL);
gst_element_link (src, sink);
/* setup special stuff */
g_object_set (ELEMENT, "signal-handoffs", TRUE, NULL);
g_signal_connect (ELEMENT, "handoff", (GCallback) cb_handoff, NULL);
/* run pipeline */
g_print ("running...\n");
if (gst_element_set_state (pipeline, GST_STATE_PLAYING) != GST_STATE_SUCCESS)
g_assert_not_reached ();
while (gst_bin_iterate (GST_BIN (pipeline)));
g_print ("cleaning up...\n");
gst_object_unref (GST_OBJECT (pipeline));
pipeline = NULL;
g_print ("done.\n");
return 0;
}

View file

@ -0,0 +1,61 @@
/* GStreamer
* Copyright (C) 2004 Benjamin Otte <in7y118@public.uni-hamburg.de>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <gst/gst.h>
GstElement *pipeline, *src, *sink;
static void
cb_handoff (GstElement * element, GstBuffer * buffer, GstPad * pad,
gpointer unused)
{
if (pipeline) {
g_print ("unreffing...\n");
gst_object_unref (GST_OBJECT (pipeline));
pipeline = NULL;
}
}
gint
main (gint argc, gchar ** argv)
{
gst_init (&argc, &argv);
g_print ("setting up...\n");
/* setup pipeline */
pipeline = gst_element_factory_make ("pipeline", NULL);
g_assert (pipeline);
src = gst_element_factory_make ("fakesrc", NULL);
g_assert (src);
sink = gst_element_factory_make ("fakesink", NULL);
g_assert (sink);
gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL);
gst_element_link (src, sink);
/* setup special stuff */
g_object_set (ELEMENT, "signal-handoffs", TRUE, NULL);
g_signal_connect (ELEMENT, "handoff", (GCallback) cb_handoff, NULL);
/* run pipeline */
g_print ("running...\n");
if (gst_element_set_state (pipeline, GST_STATE_PLAYING) != GST_STATE_SUCCESS)
g_assert_not_reached ();
while (pipeline && gst_bin_iterate (GST_BIN (pipeline)));
g_print ("done.\n");
return 0;
}

View file

@ -0,0 +1,50 @@
/* GStreamer
* Copyright (C) 2004 Benjamin Otte <in7y118@public.uni-hamburg.de>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <gst/gst.h>
gint
main (gint argc, gchar ** argv)
{
GstElement *pipeline;
GError *error = NULL;
guint i = 0;
gst_init (&argc, &argv);
g_print ("setting up...\n");
/* setup pipeline */
pipeline = gst_parse_launch ("pipeline.( { fakesrc ! fakesink } )", &error);
g_assert (error == NULL);
g_assert (pipeline);
/* run pipeline */
g_print ("running...\n");
if (gst_element_set_state (pipeline, GST_STATE_PLAYING) != GST_STATE_SUCCESS)
g_assert_not_reached ();
while (i < 100 && gst_bin_iterate (GST_BIN (pipeline)))
i++;
g_print ("cleaning up... (%d iterations)\n", i);
g_assert (i == 100);
gst_object_unref (GST_OBJECT (pipeline));
pipeline = NULL;
g_print ("done.\n");
return 0;
}