snapshot for matth to work with while I fly over to Europe....

Original commit message from CVS:
snapshot for matth to work with while I fly over to Europe....
This commit is contained in:
Erik Walthinsen 2001-03-30 00:06:43 +00:00
parent 8a10800420
commit f75bb0f38b
13 changed files with 186 additions and 184 deletions

View file

@ -2,3 +2,4 @@ Erik Walthinsen <omega@cse.ogi.edu>
Wim Taymans <wim.taymans@tvd.be> Wim Taymans <wim.taymans@tvd.be>
Richard Boulton <richard@tartarus.org> Richard Boulton <richard@tartarus.org>
Chris Emerson (PPC port) Chris Emerson (PPC port)
Zaheer Merali <zaheer@grid9.net> (thread synchronization rework)

View file

@ -19,7 +19,11 @@ bin_SCRIPTS = gstreamer-config
m4datadir = $(datadir)/aclocal m4datadir = $(datadir)/aclocal
m4data_DATA = gstreamer.m4 m4data_DATA = gstreamer.m4
EXTRA_DIST = gstreamer.spec.in gstreamer-config.in gstreamer.m4 LICENSE REQUIREMENTS ABOUT-NLS pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = gstreamer.pc
EXTRA_DIST = gstreamer.spec.in gstreamer-config.in gstreamer.m4 gstreamer.pc.in \
LICENSE REQUIREMENTS ABOUT-NLS
dist-hook: dist-hook:
cp gstreamer.spec $(distdir) cp gstreamer.spec $(distdir)

View file

@ -757,5 +757,6 @@ docs/manual/Makefile
docs/fwg/Makefile docs/fwg/Makefile
stamp.h stamp.h
gstreamer-config gstreamer-config
gstreamer.spec]) gstreamer.spec
gstreamer.pc])
AC_OUTPUT_COMMANDS([chmod +x gstreamer-config]) AC_OUTPUT_COMMANDS([chmod +x gstreamer-config])

View file

@ -210,7 +210,7 @@ gst_bin_set_element_sched (GstElement *element,GstSchedule *sched)
// otherwise, if it's just a regular old element // otherwise, if it's just a regular old element
} else { } else {
g_print("calling schedule_add_element (%p, \"%s\")\n",sched, GST_ELEMENT_NAME(element)); //g_print("calling schedule_add_element (%p, \"%s\")\n",sched, GST_ELEMENT_NAME(element));
GST_SCHEDULE_ADD_ELEMENT (sched, element); GST_SCHEDULE_ADD_ELEMENT (sched, element);
} }
} }
@ -264,10 +264,8 @@ gst_bin_add (GstBin *bin,
GST_DEBUG_ENTER (""); GST_DEBUG_ENTER ("");
// must be NULL or PAUSED state in order to modify bin // must be not be in PLAYING state in order to modify bin
// FIXME this isn't right any more g_return_if_fail (GST_STATE (bin) != GST_STATE_PLAYING);
g_return_if_fail ((GST_STATE (bin) == GST_STATE_NULL) ||
(GST_STATE (bin) == GST_STATE_PAUSED));
// the element must not already have a parent // the element must not already have a parent
g_return_if_fail (GST_ELEMENT_PARENT(element) == NULL); g_return_if_fail (GST_ELEMENT_PARENT(element) == NULL);
@ -311,9 +309,8 @@ gst_bin_remove (GstBin *bin,
g_return_if_fail (GST_IS_ELEMENT (element)); g_return_if_fail (GST_IS_ELEMENT (element));
g_return_if_fail (bin->children != NULL); g_return_if_fail (bin->children != NULL);
// must be NULL or PAUSED state in order to modify bin // must not be in PLAYING state in order to modify bin
g_return_if_fail ((GST_STATE (bin) == GST_STATE_NULL) || g_return_if_fail (GST_STATE (bin) != GST_STATE_PLAYING);
(GST_STATE (bin) == GST_STATE_PAUSED));
// the element must have its parent set to the current bin // the element must have its parent set to the current bin
g_return_if_fail (GST_ELEMENT_PARENT(element) == (GstElement *)bin); g_return_if_fail (GST_ELEMENT_PARENT(element) == (GstElement *)bin);

View file

@ -700,6 +700,9 @@ gst_element_set_state (GstElement *element, GstElementState state)
g_return_val_if_fail (element != NULL, GST_STATE_FAILURE); g_return_val_if_fail (element != NULL, GST_STATE_FAILURE);
g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_FAILURE); g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_FAILURE);
GST_DEBUG (GST_CAT_STATES,"setting element '%s' to state %s\n",GST_ELEMENT_NAME (element),
_gst_print_statename(state));
/* start with the current state */ /* start with the current state */
curpending = GST_STATE(element); curpending = GST_STATE(element);
@ -712,6 +715,8 @@ gst_element_set_state (GstElement *element, GstElementState state)
/* set the pending state variable */ /* set the pending state variable */
// FIXME: should probably check to see that we don't already have one // FIXME: should probably check to see that we don't already have one
GST_STATE_PENDING (element) = curpending; GST_STATE_PENDING (element) = curpending;
GST_DEBUG (GST_CAT_STATES,"intermediate: setting element '%s' to state %s\n",
GST_ELEMENT_NAME (element),_gst_print_statename(curpending));
/* call the state change function so it can set the state */ /* call the state change function so it can set the state */
oclass = GST_ELEMENT_CLASS (GTK_OBJECT (element)->klass); oclass = GST_ELEMENT_CLASS (GTK_OBJECT (element)->klass);
@ -767,8 +772,8 @@ gst_element_change_state (GstElement *element)
g_return_val_if_fail (element != NULL, GST_STATE_FAILURE); g_return_val_if_fail (element != NULL, GST_STATE_FAILURE);
g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_FAILURE); g_return_val_if_fail (GST_IS_ELEMENT (element), GST_STATE_FAILURE);
// g_print("gst_element_change_state(\"%s\",%d)\n", GST_DEBUG (GST_CAT_STATES, "default handler sets '%s' state to %s\n",
// element->name,state); GST_ELEMENT_NAME (element), _gst_print_statename(GST_STATE_PENDING(element)));
if (GST_STATE_TRANSITION(element) == GST_STATE_READY_TO_PLAYING) if (GST_STATE_TRANSITION(element) == GST_STATE_READY_TO_PLAYING)
GST_SCHEDULE_ENABLE_ELEMENT (element->sched,element); GST_SCHEDULE_ENABLE_ELEMENT (element->sched,element);

View file

@ -574,8 +574,11 @@ gst_pad_connect (GstPad *srcpad,
gtk_signal_emit(GTK_OBJECT(realsrc), gst_real_pad_signals[REAL_CONNECTED], realsink); gtk_signal_emit(GTK_OBJECT(realsrc), gst_real_pad_signals[REAL_CONNECTED], realsink);
gtk_signal_emit(GTK_OBJECT(realsink), gst_real_pad_signals[REAL_CONNECTED], realsrc); gtk_signal_emit(GTK_OBJECT(realsink), gst_real_pad_signals[REAL_CONNECTED], realsrc);
// now tell the scheduler // now tell the scheduler(s)
if (realsrc->sched)
GST_SCHEDULE_PAD_CONNECT (realsrc->sched, realsrc, realsink); GST_SCHEDULE_PAD_CONNECT (realsrc->sched, realsrc, realsink);
else if (realsink->sched)
GST_SCHEDULE_PAD_CONNECT (realsink->sched, realsrc, realsink);
GST_INFO (GST_CAT_ELEMENT_PADS, "connected %s:%s and %s:%s", GST_INFO (GST_CAT_ELEMENT_PADS, "connected %s:%s and %s:%s",
GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad)); GST_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad));

View file

@ -862,6 +862,7 @@ gst_schedule_chain_new (GstSchedule *sched)
{ {
GstScheduleChain *chain = g_new (GstScheduleChain, 1); GstScheduleChain *chain = g_new (GstScheduleChain, 1);
// initialize the chain with sane values
chain->sched = sched; chain->sched = sched;
chain->disabled = NULL; chain->disabled = NULL;
chain->elements = NULL; chain->elements = NULL;
@ -870,6 +871,7 @@ gst_schedule_chain_new (GstSchedule *sched)
chain->cothreaded_elements = 0; chain->cothreaded_elements = 0;
chain->schedule = FALSE; chain->schedule = FALSE;
// add the chain to the schedules' list of chains
sched->chains = g_list_prepend (sched->chains, chain); sched->chains = g_list_prepend (sched->chains, chain);
sched->num_chains++; sched->num_chains++;
@ -881,11 +883,13 @@ gst_schedule_chain_new (GstSchedule *sched)
void void
gst_schedule_chain_destroy (GstScheduleChain *chain) gst_schedule_chain_destroy (GstScheduleChain *chain)
{ {
// remove the chain from the schedules' list of chains
chain->sched->chains = g_list_remove (chain->sched->chains, chain); chain->sched->chains = g_list_remove (chain->sched->chains, chain);
chain->sched->num_chains--; chain->sched->num_chains--;
g_list_free (chain->disabled); // destroy the chain
g_list_free (chain->elements); g_list_free (chain->disabled); // should be empty...
g_list_free (chain->elements); // ditto
g_free (chain); g_free (chain);
} }
@ -925,7 +929,8 @@ gst_schedule_chain_disable_element (GstScheduleChain *chain, GstElement *element
chain->disabled = g_list_prepend (chain->disabled, element); chain->disabled = g_list_prepend (chain->disabled, element);
// reschedule the chain // reschedule the chain
gst_schedule_cothreaded_chain(GST_BIN(chain->sched->parent),chain); // FIXME this should be done only if manager state != NULL
// gst_schedule_cothreaded_chain(GST_BIN(chain->sched->parent),chain);
} }
void void
@ -938,8 +943,13 @@ gst_schedule_chain_remove_element (GstScheduleChain *chain, GstElement *element)
gst_schedule_chain_disable_element (chain, element); gst_schedule_chain_disable_element (chain, element);
} }
// remove the element from the list of elements
chain->disabled = g_list_remove (chain->disabled, element); chain->disabled = g_list_remove (chain->disabled, element);
chain->num_elements--; chain->num_elements--;
// if there are no more elements in the chain, destroy the chain
if (chain->num_elements == 0)
gst_schedule_chain_destroy(chain);
} }
void void
@ -1015,7 +1025,7 @@ gst_schedule_pad_connect (GstSchedule *sched, GstPad *srcpad, GstPad *sinkpad)
GST_INFO (GST_CAT_SCHEDULING, "have pad connected callback on %s:%s",GST_DEBUG_PAD_NAME(srcpad)); GST_INFO (GST_CAT_SCHEDULING, "have pad connected callback on %s:%s",GST_DEBUG_PAD_NAME(srcpad));
if ((peerelement = gst_schedule_check_pad(sched,srcpad))) { if ((peerelement = gst_schedule_check_pad(sched,srcpad))) {
GST_INFO (GST_CAT_SCHEDULING, "peer is in same schedule, chaining together"); GST_INFO (GST_CAT_SCHEDULING, "peer %s:%s is in same schedule, chaining together",GST_DEBUG_PAD_NAME(sinkpad));
gst_schedule_chain_elements (sched, GST_ELEMENT(GST_PAD_PARENT(srcpad)), peerelement); gst_schedule_chain_elements (sched, GST_ELEMENT(GST_PAD_PARENT(srcpad)), peerelement);
} }
} }
@ -1097,18 +1107,12 @@ gst_schedule_pad_disconnect (GstSchedule *sched, GstPad *srcpad, GstPad *sinkpad
// now create a new chain to hold element1 and build it from scratch // now create a new chain to hold element1 and build it from scratch
chain1 = gst_schedule_chain_new (sched); chain1 = gst_schedule_chain_new (sched);
gst_schedule_chain_recursive_add (chain1, element1); gst_schedule_chain_recursive_add (chain1, element1);
// this is an ugly hack to handle elements left over
if (chain1->num_elements == 1)
gst_schedule_chain_destroy(chain1);
// check the other element to see if it landed in the newly created chain // check the other element to see if it landed in the newly created chain
if (gst_schedule_find_chain (sched, element2) == NULL) { if (gst_schedule_find_chain (sched, element2) == NULL) {
// if not in chain, create chain and build from scratch // if not in chain, create chain and build from scratch
chain2 = gst_schedule_chain_new (sched); chain2 = gst_schedule_chain_new (sched);
gst_schedule_chain_recursive_add (chain2, element2); gst_schedule_chain_recursive_add (chain2, element2);
// this is an ugly hack to handle elements left over
if (chain2->num_elements == 1)
gst_schedule_chain_destroy(chain2);
} }
} }
@ -1119,6 +1123,7 @@ gst_schedule_add_element (GstSchedule *sched, GstElement *element)
GList *pads; GList *pads;
GstPad *pad; GstPad *pad;
GstElement *peerelement; GstElement *peerelement;
GstScheduleChain *chain;
g_return_if_fail (element != NULL); g_return_if_fail (element != NULL);
g_return_if_fail (GST_IS_ELEMENT(element)); g_return_if_fail (GST_IS_ELEMENT(element));
@ -1126,12 +1131,19 @@ gst_schedule_add_element (GstSchedule *sched, GstElement *element)
GST_INFO (GST_CAT_SCHEDULING, "adding element \"%s\" to schedule", GST_INFO (GST_CAT_SCHEDULING, "adding element \"%s\" to schedule",
GST_ELEMENT_NAME(element)); GST_ELEMENT_NAME(element));
// set the sched pointer in the element itself
gst_element_set_sched (element, sched);
// only deal with elements after this point, not bins
if (GST_IS_BIN (element)) return;
// first add it to the list of elements that are to be scheduled // first add it to the list of elements that are to be scheduled
sched->elements = g_list_prepend (sched->elements, element); sched->elements = g_list_prepend (sched->elements, element);
sched->num_elements++; sched->num_elements++;
// set the sched pointer in the element itself // create a chain to hold it, and add
gst_element_set_sched (element, sched); chain = gst_schedule_chain_new (sched);
gst_schedule_chain_add_element (chain, element);
// set the sched pointer in all the pads // set the sched pointer in all the pads
pads = element->pads; pads = element->pads;
@ -1185,6 +1197,8 @@ gst_schedule_disable_element (GstSchedule *sched, GstElement *element)
void void
gst_schedule_remove_element (GstSchedule *sched, GstElement *element) gst_schedule_remove_element (GstSchedule *sched, GstElement *element)
{ {
GstScheduleChain *chain;
g_return_if_fail (element != NULL); g_return_if_fail (element != NULL);
g_return_if_fail (GST_IS_ELEMENT(element)); g_return_if_fail (GST_IS_ELEMENT(element));
@ -1192,15 +1206,21 @@ gst_schedule_remove_element (GstSchedule *sched, GstElement *element)
GST_INFO (GST_CAT_SCHEDULING, "removing element \"%s\" from schedule", GST_INFO (GST_CAT_SCHEDULING, "removing element \"%s\" from schedule",
GST_ELEMENT_NAME(element)); GST_ELEMENT_NAME(element));
// disable the element, i.e. remove from chain // find what chain the element is in
gst_schedule_disable_element (sched, element); chain = gst_schedule_find_chain(sched, element);
// unset the scheduler // disable the element, i.e. remove from chain's active list
gst_element_set_sched (element, NULL); gst_schedule_chain_disable_element (chain, element);
// remove it from its chain
gst_schedule_chain_remove_element (chain, element);
// remove it from the list of elements // remove it from the list of elements
sched->elements = g_list_remove (sched->elements, element); sched->elements = g_list_remove (sched->elements, element);
sched->num_elements--; sched->num_elements--;
// unset the scheduler pointer in the element
gst_element_set_sched (element, NULL);
} }
} }
@ -1213,6 +1233,7 @@ gst_schedule_iterate (GstSchedule *sched)
GstElement *entry; GstElement *entry;
gint num_scheduled = 0; gint num_scheduled = 0;
gboolean eos = FALSE; gboolean eos = FALSE;
GList *elements;
GST_DEBUG_ENTER("(\"%s\")", GST_ELEMENT_NAME (bin)); GST_DEBUG_ENTER("(\"%s\")", GST_ELEMENT_NAME (bin));
@ -1222,7 +1243,8 @@ gst_schedule_iterate (GstSchedule *sched)
// step through all the chains // step through all the chains
chains = sched->chains; chains = sched->chains;
if (chains == NULL) return FALSE; // if (chains == NULL) return FALSE;
g_return_val_if_fail (chains != NULL, FALSE);
while (chains) { while (chains) {
chain = (GstScheduleChain *)(chains->data); chain = (GstScheduleChain *)(chains->data);
chains = g_list_next (chains); chains = g_list_next (chains);
@ -1235,8 +1257,17 @@ gst_schedule_iterate (GstSchedule *sched)
GST_DEBUG (GST_CAT_DATAFLOW,"starting iteration via cothreads\n"); GST_DEBUG (GST_CAT_DATAFLOW,"starting iteration via cothreads\n");
if (chain->elements) { if (chain->elements) {
elements = chain->elements;
//printf("searching for non-decoupled element\n");
while (elements) {
entry = GST_ELEMENT(elements->data);
elements = g_list_next(elements);
//printf("checking %s\n",GST_ELEMENT_NAME(entry));
if (!GST_FLAG_IS_SET(entry,GST_ELEMENT_DECOUPLED)) break;
}
//printf("found non-decoupled element\n");
// FIXME FIXME FIXME need to not use a DECOUPLED element as entry // FIXME FIXME FIXME need to not use a DECOUPLED element as entry
entry = GST_ELEMENT (chain->elements->data); // entry = GST_ELEMENT (chain->elements->data);
if (entry) { if (entry) {
GST_FLAG_SET (entry, GST_ELEMENT_COTHREAD_STOPPING); GST_FLAG_SET (entry, GST_ELEMENT_COTHREAD_STOPPING);
GST_DEBUG (GST_CAT_DATAFLOW,"set COTHREAD_STOPPING flag on \"%s\"(@%p)\n", GST_DEBUG (GST_CAT_DATAFLOW,"set COTHREAD_STOPPING flag on \"%s\"(@%p)\n",

View file

@ -118,9 +118,9 @@ void gst_schedule_enable_element (GstSchedule *sched, GstElement *element);
void gst_schedule_disable_element (GstSchedule *sched, GstElement *element); void gst_schedule_disable_element (GstSchedule *sched, GstElement *element);
void gst_schedule_pad_connect (GstSchedule *sched, GstPad *srcpad, GstPad *sinkpad); void gst_schedule_pad_connect (GstSchedule *sched, GstPad *srcpad, GstPad *sinkpad);
void gst_schedule_pad_disconnect (GstSchedule *sched, GstPad *srcpad, GstPad *sinkpad); void gst_schedule_pad_disconnect (GstSchedule *sched, GstPad *srcpad, GstPad *sinkpad);
gboolean gst_schedule_iterate (GstSchedule *sched);
void gst_schedule_show (GstSchedule *sched); void gst_schedule_show (GstSchedule *sched);
gboolean gst_schedule_iterate (GstSchedule *sched);
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -68,8 +68,7 @@ static GstElementStateReturn gst_thread_change_state (GstElement *element);
static xmlNodePtr gst_thread_save_thyself (GstObject *object, xmlNodePtr parent); static xmlNodePtr gst_thread_save_thyself (GstObject *object, xmlNodePtr parent);
static void gst_thread_restore_thyself (GstObject *object, xmlNodePtr self); static void gst_thread_restore_thyself (GstObject *object, xmlNodePtr self);
static void gst_thread_signal_thread (GstThread *thread, guint syncflag,gboolean set); static void gst_thread_signal_thread (GstThread *thread, gboolean spinning);
static void gst_thread_wait_thread (GstThread *thread, guint syncflag,gboolean set);
static void static void
gst_thread_wait_two_thread (GstThread *thread, guint syncflag, gboolean set,guint syncflag2, gboolean set2); gst_thread_wait_two_thread (GstThread *thread, guint syncflag, gboolean set,guint syncflag2, gboolean set2);
static void gst_thread_schedule_dummy (GstBin *bin); static void gst_thread_schedule_dummy (GstBin *bin);
@ -255,13 +254,16 @@ gst_thread_change_state (GstElement *element)
GST_DEBUG (GST_CAT_THREAD, "creating thread \"%s\"\n", GST_DEBUG (GST_CAT_THREAD, "creating thread \"%s\"\n",
GST_ELEMENT_NAME (GST_ELEMENT (element))); GST_ELEMENT_NAME (GST_ELEMENT (element)));
g_mutex_lock(thread->lock);
// create the thread // create the thread
pthread_create (&thread->thread_id, NULL, pthread_create (&thread->thread_id, NULL,
gst_thread_main_loop, thread); gst_thread_main_loop, thread);
// wait for it to 'spin up' // wait for it to 'spin up'
GST_DEBUG (GST_CAT_THREAD, "sync: waiting for spinup\n"); GST_DEBUG (GST_CAT_THREAD, "sync: waiting for spinup\n");
gst_thread_wait_thread (thread,GST_THREAD_STATE_STARTED,TRUE); g_cond_wait(thread->cond,thread->lock);
g_mutex_unlock(thread->lock);
GST_DEBUG (GST_CAT_THREAD, "sync: thread claims to be up\n"); GST_DEBUG (GST_CAT_THREAD, "sync: thread claims to be up\n");
} else { } else {
GST_INFO (GST_CAT_THREAD, "NOT starting thread \"%s\"", GST_INFO (GST_CAT_THREAD, "NOT starting thread \"%s\"",
@ -279,38 +281,23 @@ gst_thread_change_state (GstElement *element)
GST_ELEMENT_NAME (GST_ELEMENT (element))); GST_ELEMENT_NAME (GST_ELEMENT (element)));
GST_DEBUG(0,"sync: telling thread to start spinning\n"); GST_DEBUG(0,"sync: telling thread to start spinning\n");
gst_thread_signal_thread (thread,GST_THREAD_STATE_SPINNING,TRUE); gst_thread_signal_thread(thread,TRUE);
GST_DEBUG(0,"sync: done telling thread to start spinning\n");
GST_INFO(GST_CAT_THREAD, "waiting for thread to start up");
gst_thread_wait_thread (thread,GST_THREAD_STATE_ELEMENT_CHANGED,TRUE);
g_mutex_lock(thread->lock);
GST_FLAG_UNSET(thread,GST_THREAD_STATE_ELEMENT_CHANGED);
g_mutex_unlock(thread->lock);
break; break;
case GST_STATE_PLAYING_TO_PAUSED: case GST_STATE_PLAYING_TO_PAUSED:
GST_INFO (GST_CAT_THREAD,"pausing thread \"%s\"", GST_INFO (GST_CAT_THREAD,"pausing thread \"%s\"",
GST_ELEMENT_NAME (GST_ELEMENT (element))); GST_ELEMENT_NAME (GST_ELEMENT (element)));
//GST_FLAG_UNSET(thread,GST_THREAD_STATE_SPINNING); gst_thread_signal_thread(thread,FALSE);
gst_thread_signal_thread (thread,GST_THREAD_STATE_SPINNING,FALSE);
gst_thread_wait_thread (thread,GST_THREAD_STATE_ELEMENT_CHANGED,TRUE);
g_mutex_lock(thread->lock);
GST_FLAG_UNSET(thread,GST_THREAD_STATE_ELEMENT_CHANGED);
g_mutex_unlock(thread->lock);
break; break;
case GST_STATE_PLAYING_TO_READY: case GST_STATE_PLAYING_TO_READY:
gst_thread_signal_thread (thread,GST_THREAD_STATE_SPINNING,FALSE); gst_thread_signal_thread(thread,FALSE);
gst_thread_wait_thread (thread,GST_THREAD_STATE_ELEMENT_CHANGED,TRUE);
g_mutex_lock(thread->lock);
GST_FLAG_UNSET(thread,GST_THREAD_STATE_ELEMENT_CHANGED);
g_mutex_unlock(thread->lock);
break; break;
case GST_STATE_READY_TO_NULL: case GST_STATE_READY_TO_NULL:
GST_INFO (GST_CAT_THREAD,"stopping thread \"%s\"", GST_INFO (GST_CAT_THREAD,"stopping thread \"%s\"",
GST_ELEMENT_NAME (GST_ELEMENT (element))); GST_ELEMENT_NAME (GST_ELEMENT (element)));
//GST_FLAG_SET (thread, GST_THREAD_STATE_REAPING); GST_FLAG_SET (thread, GST_THREAD_STATE_REAPING);
gst_thread_signal_thread (thread,GST_THREAD_STATE_REAPING,TRUE); gst_thread_signal_thread(thread,FALSE);
pthread_join(thread->thread_id,NULL); pthread_join(thread->thread_id,NULL);
@ -320,7 +307,7 @@ gst_thread_change_state (GstElement *element)
GST_FLAG_UNSET(thread,GST_THREAD_STATE_ELEMENT_CHANGED); GST_FLAG_UNSET(thread,GST_THREAD_STATE_ELEMENT_CHANGED);
if (GST_ELEMENT_CLASS (parent_class)->change_state) if (GST_ELEMENT_CLASS (parent_class)->change_state)
stateset = GST_ELEMENT_CLASS (parent_class)->change_state (thread); stateset = GST_ELEMENT_CLASS (parent_class)->change_state (GST_ELEMENT(thread));
break; break;
default: default:
@ -330,6 +317,16 @@ gst_thread_change_state (GstElement *element)
return stateset; return stateset;
} }
static void gst_thread_update_state (GstThread *thread)
{
// check for state change
if (GST_STATE_PENDING(thread) != GST_STATE_NONE_PENDING) {
// punt and change state on all the children
if (GST_ELEMENT_CLASS (parent_class)->change_state)
GST_ELEMENT_CLASS (parent_class)->change_state (GST_ELEMENT(thread));
}
}
/** /**
* gst_thread_main_loop: * gst_thread_main_loop:
* @arg: the thread to start * @arg: the thread to start
@ -341,8 +338,8 @@ static void *
gst_thread_main_loop (void *arg) gst_thread_main_loop (void *arg)
{ {
GstThread *thread = GST_THREAD (arg); GstThread *thread = GST_THREAD (arg);
gboolean first = 1;
gint stateset; gint stateset;
gboolean isSpinning = FALSE;
GST_INFO (GST_CAT_THREAD,"thread \"%s\" is running with PID %d", GST_INFO (GST_CAT_THREAD,"thread \"%s\" is running with PID %d",
GST_ELEMENT_NAME (GST_ELEMENT (thread)), getpid ()); GST_ELEMENT_NAME (GST_ELEMENT (thread)), getpid ());
@ -357,57 +354,47 @@ gst_thread_main_loop (void *arg)
if (GST_BIN_CLASS (parent_class)->schedule) if (GST_BIN_CLASS (parent_class)->schedule)
GST_BIN_CLASS (parent_class)->schedule (GST_BIN (thread)); GST_BIN_CLASS (parent_class)->schedule (GST_BIN (thread));
GST_DEBUG(0, "sync: indicating spinup\n"); GST_DEBUG (GST_CAT_THREAD, "sync: indicating spinup\n");
gst_thread_signal_thread (thread,GST_THREAD_STATE_STARTED,TRUE); g_mutex_lock (thread->lock);
GST_DEBUG(0, "sync: done indicating spinup\n"); g_cond_signal (thread->cond);
// don't unlock the mutex because we hold it into the top of the while loop
GST_INFO (GST_CAT_THREAD,"sync: thread has signaled to parent at startup"); GST_DEBUG (GST_CAT_THREAD, "sync: thread has indicated spinup to main process\n");
while (!GST_FLAG_IS_SET (thread, GST_THREAD_STATE_REAPING)) { while (!GST_FLAG_IS_SET (thread, GST_THREAD_STATE_REAPING)) {
if (GST_FLAG_IS_SET (thread, GST_THREAD_STATE_SPINNING)) { // start out by waiting for a state change into spinning
isSpinning=TRUE; GST_DEBUG (GST_CAT_THREAD, "sync: waiting at top of while for signal from main process\n");
g_cond_wait (thread->cond,thread->lock);
GST_DEBUG (GST_CAT_THREAD, "sync: main process has signaled at top of while\n");
// now is a good time to change the state of the children and the thread itself
gst_thread_update_state (thread);
GST_DEBUG (GST_CAT_THREAD, "sync: done changing state, signaling back\n");
g_cond_signal (thread->cond);
g_mutex_unlock (thread->lock);
GST_DEBUG (GST_CAT_THREAD, "sync: done syncing with main thread at top of while\n");
while (GST_FLAG_IS_SET (thread, GST_THREAD_STATE_SPINNING)) {
if (!gst_bin_iterate (GST_BIN (thread))) { if (!gst_bin_iterate (GST_BIN (thread))) {
/*g_mutex_lock(thread->lock);
GST_FLAG_UNSET (thread, GST_THREAD_STATE_SPINNING); GST_FLAG_UNSET (thread, GST_THREAD_STATE_SPINNING);
GST_DEBUG(0,"sync: removed spinning state due to failed iteration\n"); GST_DEBUG(0,"sync: removed spinning state due to failed iteration\n");
g_mutex_unlock(thread->lock);*/
gst_thread_wait_two_thread(thread,GST_THREAD_STATE_REAPING,TRUE,
GST_THREAD_STATE_SPINNING,FALSE);
} }
} }
else {
if (isSpinning==TRUE) {
GST_DEBUG(0,"sync: got a pause or playing to ready transition");
isSpinning=FALSE;
// check for state change
if (GST_STATE_PENDING(thread)) {
// punt and change state on all the children
if (GST_ELEMENT_CLASS (parent_class)->change_state)
stateset = GST_ELEMENT_CLASS (parent_class)->change_state (thread);
}
gst_thread_signal_thread (thread,GST_THREAD_STATE_ELEMENT_CHANGED,TRUE);
}
GST_DEBUG (0, "sync: thread \"%s\" waiting\n", GST_ELEMENT_NAME (GST_ELEMENT (thread))); GST_DEBUG (GST_CAT_THREAD, "sync: waiting at bottom of while for signal from main process\n");
gst_thread_wait_two_thread (thread,GST_THREAD_STATE_SPINNING,TRUE, g_mutex_lock (thread->lock);
GST_THREAD_STATE_REAPING,TRUE); GST_DEBUG (GST_CAT_THREAD, "sync: signaling that the thread is out of the SPINNING loop\n");
GST_DEBUG (0, "sync: done waiting\n"); g_cond_signal (thread->cond);
isSpinning=TRUE; g_cond_wait (thread->cond, thread->lock);
// if reaping was returned, break outof while loop GST_DEBUG (GST_CAT_THREAD, "sync: main process has signaled at bottom of while\n");
if (GST_FLAG_IS_SET(thread,GST_THREAD_STATE_REAPING)) { // now change the children's and thread's state
break; gst_thread_update_state (thread);
GST_DEBUG (GST_CAT_THREAD, "sync: done changing state, signaling back\n");
g_cond_signal (thread->cond);
// don't release the mutex, we hold that into the top of the loop
GST_DEBUG (GST_CAT_THREAD, "sync: done syncning with main thread at bottom of while\n");
} }
// check for state change // since we don't unlock at the end of the while loop, do it here
if (GST_STATE_PENDING(thread)) { g_mutex_unlock (thread->lock);
// punt and change state on all the children
if (GST_ELEMENT_CLASS (parent_class)->change_state)
stateset = GST_ELEMENT_CLASS (parent_class)->change_state (thread);
}
gst_thread_signal_thread (thread,GST_THREAD_STATE_ELEMENT_CHANGED,TRUE);
}
}
GST_INFO (GST_CAT_THREAD, "gstthread: thread \"%s\" is stopped", GST_INFO (GST_CAT_THREAD, "gstthread: thread \"%s\" is stopped",
GST_ELEMENT_NAME (thread)); GST_ELEMENT_NAME (thread));
@ -416,76 +403,27 @@ gst_thread_main_loop (void *arg)
// the set flag is to say whether it should set TRUE or FALSE // the set flag is to say whether it should set TRUE or FALSE
static void static void
gst_thread_signal_thread (GstThread *thread, guint syncflag, gboolean set) gst_thread_signal_thread (GstThread *thread, gboolean spinning)
{ {
// set the spinning state
if (spinning) GST_FLAG_SET(thread,GST_THREAD_STATE_SPINNING);
else GST_FLAG_SET (thread, GST_THREAD_STATE_SPINNING);
GST_DEBUG (GST_CAT_THREAD, "sync-main: locking\n");
g_mutex_lock(thread->lock); g_mutex_lock(thread->lock);
GST_DEBUG (0,"sync: signaling thread setting %u to %d\n",syncflag,set);
if (set) if (!spinning) {
GST_FLAG_SET(thread,syncflag); GST_DEBUG (GST_CAT_THREAD, "sync-main: waiting for spindown\n");
else g_cond_wait (thread->cond, thread->lock);
GST_FLAG_UNSET(thread,syncflag); }
GST_DEBUG (GST_CAT_THREAD, "sync-main: signaling\n");
g_cond_signal (thread->cond); g_cond_signal (thread->cond);
g_mutex_unlock (thread->lock); GST_DEBUG (GST_CAT_THREAD, "sync-main: waiting for ack\n");
GST_DEBUG (0,"sync: done signaling thread with %u set to %u..should be %d\n",syncflag, g_cond_wait (thread->cond,thread->lock);
GST_FLAG_IS_SET(thread,syncflag),set);
}
// the set flag is to see what flag to wait for GST_DEBUG (GST_CAT_THREAD, "sync-main: unlocking\n");
static void
gst_thread_wait_thread (GstThread *thread, guint syncflag, gboolean set)
{
// if (!thread->signaling) {
GTimeVal finaltime;
g_mutex_lock (thread->lock);
GST_DEBUG (0,"sync: waiting for thread for %u to be set %d\n",
syncflag,set);
while ((!GST_FLAG_IS_SET(thread,syncflag) && set==TRUE) ||
(GST_FLAG_IS_SET(thread,syncflag) && set==FALSE)) {
g_get_current_time(&finaltime);
if (finaltime.tv_usec>995000) {
finaltime.tv_sec++;
finaltime.tv_usec=5000-(1000000-finaltime.tv_usec);
}
else {
finaltime.tv_usec+=5000;
}
g_cond_timed_wait (thread->cond, thread->lock,&finaltime);
}
g_mutex_unlock(thread->lock); g_mutex_unlock(thread->lock);
GST_DEBUG (0, "sync: done waiting for thread for %u to be set %d\n", GST_DEBUG (GST_CAT_THREAD, "sync-main: unlocked\n");
syncflag,set);
// }
}
// the set flag is to see what flag to wait for
static void
gst_thread_wait_two_thread (GstThread *thread, guint syncflag, gboolean set,
guint syncflag2, gboolean set2)
{
// if (!thread->signaling) {
GTimeVal finaltime;
g_mutex_lock (thread->lock);
GST_DEBUG (0,"sync: waiting for thread for %u to be set %d or %u to be set %d\n",
syncflag,set,syncflag2,set);
while (((!GST_FLAG_IS_SET(thread,syncflag) && set==TRUE) ||
(GST_FLAG_IS_SET(thread,syncflag) && set==FALSE)) &&
((!GST_FLAG_IS_SET(thread,syncflag2) && set2==TRUE) ||
(GST_FLAG_IS_SET(thread,syncflag2) && set==FALSE)))
{
g_get_current_time(&finaltime);
if (finaltime.tv_usec>995000) {
finaltime.tv_sec++;
finaltime.tv_usec=5000-(1000000-finaltime.tv_usec);
}
else {
finaltime.tv_usec+=5000;
}
g_cond_timed_wait (thread->cond, thread->lock,&finaltime);
}
g_mutex_unlock (thread->lock);
GST_DEBUG (0, "sync: done waiting for thread for %u to be set %d or %u to be set %d\n",
syncflag,set,syncflag2,set2);
// }
} }

View file

@ -83,3 +83,4 @@ make prefix=$RPM_BUILD_ROOT%{prefix} install
%{prefix}/include/* %{prefix}/include/*
%{prefix}/lib/lib*.a %{prefix}/lib/lib*.a
%{prefix}/lib/lib*.so %{prefix}/lib/lib*.so
%{prefix}/lib/pkgconfig/*

View file

@ -1,5 +1,3 @@
<<<<<<< incsched.c
<<<<<<< incsched.c
#include <stdlib.h> #include <stdlib.h>
#include <gst/gst.h> #include <gst/gst.h>
@ -49,11 +47,11 @@ int main(int argc,char *argv[]) {
g_print("\nAdding sink to bin:\n"); g_print("\nAdding sink to bin:\n");
gst_bin_add(bin,sink); gst_bin_add(bin,sink);
gst_schedule_show(GST_ELEMENT_SCHED(bin)); gst_schedule_show(GST_ELEMENT_SCHED(thread));
g_print("\nAdding bin to thread:\n"); g_print("\nAdding bin to thread:\n");
gst_bin_add(thread, GST_ELEMENT(bin)); gst_bin_add(thread, GST_ELEMENT(bin));
gst_schedule_show(GST_ELEMENT_SCHED(bin)); gst_schedule_show(GST_ELEMENT_SCHED(thread));
g_print("\nConnecting identity to sink:\n"); g_print("\nConnecting identity to sink:\n");
gst_element_connect(identity,"src",sink,"sink"); gst_element_connect(identity,"src",sink,"sink");
@ -113,6 +111,13 @@ int main(int argc,char *argv[]) {
gst_element_connect(identity,"src",sink,"sink"); gst_element_connect(identity,"src",sink,"sink");
gst_schedule_show(GST_ELEMENT_SCHED(thread)); gst_schedule_show(GST_ELEMENT_SCHED(thread));
g_print("\n\nNow setting identity2 to NULL:\n");
gst_element_set_state(identity2,GST_STATE_NULL);
g_print("\nRemoving identity2 from bin:\n");
gst_bin_remove(bin, identity2);
gst_schedule_show(GST_ELEMENT_SCHED(thread));
g_print("\n\nNow setting state from READY to PLAYING:\n"); g_print("\n\nNow setting state from READY to PLAYING:\n");
gst_element_set_state(GST_ELEMENT(thread),GST_STATE_PLAYING); gst_element_set_state(GST_ELEMENT(thread),GST_STATE_PLAYING);
gst_schedule_show(GST_ELEMENT_SCHED(thread)); gst_schedule_show(GST_ELEMENT_SCHED(thread));

View file

@ -12,23 +12,34 @@ int main(int argc,char *argv[]) {
pipeline = gst_pipeline_new("pipeline"); pipeline = gst_pipeline_new("pipeline");
thread = gst_thread_new("thread"); thread = gst_thread_new("thread");
src = gst_elementfactory_make("fakesrc","src"); src = gst_elementfactory_make("fakesrc","src");
queue1 = gst_elementfactory_make("queue","queue");
sink = gst_elementfactory_make("fakesink","sink"); sink = gst_elementfactory_make("fakesink","sink");
gst_bin_add(pipeline,src); fprintf(stderr,"ADDING src\n");
gst_bin_add(pipeline,queue1); gst_bin_add(thread,src);
gst_bin_add(pipeline,GST_ELEMENT(thread)); fprintf(stderr,"ADDING sink\n");
gst_bin_add(thread,sink); gst_bin_add(thread,sink);
fprintf(stderr,"ADDING thread\n");
gst_bin_add(pipeline,GST_ELEMENT(thread));
gst_element_add_ghost_pad(GST_ELEMENT(thread),gst_element_get_pad(sink,"sink"),"sink"); // gst_element_add_ghost_pad(GST_ELEMENT(thread),gst_element_get_pad(sink,"sink"),"sink");
gst_element_connect (src,"src",queue1,"sink"); fprintf(stderr,"CONNECTING src to sink\n");
gst_element_connect (queue1, "src", thread, "sink"); gst_element_connect (src, "src", sink, "sink");
while (1) { fprintf(stderr,"\nSWITCHING to READY:\n");
fprintf(stderr,"SWITCHING TO READY:\n"); gst_element_set_state (thread, GST_STATE_READY);
gst_element_set_state (pipeline, GST_STATE_READY); gst_schedule_show(GST_ELEMENT_SCHED(pipeline));
fprintf(stderr,"SWITCHING TO NULL:\n"); gst_schedule_show(GST_ELEMENT_SCHED(thread));
gst_element_set_state (pipeline, GST_STATE_NULL);
} /*
fprintf(stderr,"\nSWITCHING to PLAYING:\n");
gst_element_set_state (thread, GST_STATE_PLAYING);
gst_schedule_show(GST_ELEMENT_SCHED(pipeline));
gst_schedule_show(GST_ELEMENT_SCHED(thread));
fprintf(stderr,"\nSWITCHING to READY:\n");
gst_element_set_state (thread, GST_STATE_READY);
gst_schedule_show(GST_ELEMENT_SCHED(pipeline));
gst_schedule_show(GST_ELEMENT_SCHED(thread));
*/
} }

View file

@ -25,6 +25,11 @@ main(int argc, char *argv[])
gst_parse_launch (cmdline, GST_BIN (pipeline)); gst_parse_launch (cmdline, GST_BIN (pipeline));
xmlSaveFile("launch.gst", gst_xml_write(GST_ELEMENT(pipeline)));
gst_schedule_show(GST_ELEMENT_SCHED(pipeline));
gst_schedule_show(GST_ELEMENT_SCHED(gst_bin_get_by_name(pipeline,"thread0")));
fprintf(stderr,"RUNNING pipeline\n"); fprintf(stderr,"RUNNING pipeline\n");
gst_element_set_state (pipeline, GST_STATE_PLAYING); gst_element_set_state (pipeline, GST_STATE_PLAYING);