From f75bb0f38b8e15157e1572343c54c331b657cfe7 Mon Sep 17 00:00:00 2001 From: Erik Walthinsen Date: Fri, 30 Mar 2001 00:06:43 +0000 Subject: [PATCH] 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.... --- AUTHORS | 1 + Makefile.am | 6 +- configure.in | 3 +- gst/gstbin.c | 13 +-- gst/gstelement.c | 9 +- gst/gstpad.c | 7 +- gst/gstscheduler.c | 67 +++++++++---- gst/gstscheduler.h | 2 +- gst/gstthread.c | 206 ++++++++++++++------------------------- gstreamer.spec.in | 1 + tests/incsched.c | 13 ++- tests/threadlock.c | 37 ++++--- tools/gstreamer-launch.c | 5 + 13 files changed, 186 insertions(+), 184 deletions(-) diff --git a/AUTHORS b/AUTHORS index a7e24546e2..f5f401c9db 100644 --- a/AUTHORS +++ b/AUTHORS @@ -2,3 +2,4 @@ Erik Walthinsen Wim Taymans Richard Boulton Chris Emerson (PPC port) +Zaheer Merali (thread synchronization rework) diff --git a/Makefile.am b/Makefile.am index 888cc6b333..6d363ba57b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -19,7 +19,11 @@ bin_SCRIPTS = gstreamer-config m4datadir = $(datadir)/aclocal 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: cp gstreamer.spec $(distdir) diff --git a/configure.in b/configure.in index 48239417ca..01ef2d3c76 100644 --- a/configure.in +++ b/configure.in @@ -757,5 +757,6 @@ docs/manual/Makefile docs/fwg/Makefile stamp.h gstreamer-config -gstreamer.spec]) +gstreamer.spec +gstreamer.pc]) AC_OUTPUT_COMMANDS([chmod +x gstreamer-config]) diff --git a/gst/gstbin.c b/gst/gstbin.c index 86d8e9c920..22cfcdea63 100644 --- a/gst/gstbin.c +++ b/gst/gstbin.c @@ -210,7 +210,7 @@ gst_bin_set_element_sched (GstElement *element,GstSchedule *sched) // otherwise, if it's just a regular old element } 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); } } @@ -264,10 +264,8 @@ gst_bin_add (GstBin *bin, GST_DEBUG_ENTER (""); - // must be NULL or PAUSED state in order to modify bin - // FIXME this isn't right any more - g_return_if_fail ((GST_STATE (bin) == GST_STATE_NULL) || - (GST_STATE (bin) == GST_STATE_PAUSED)); + // must be not be in PLAYING state in order to modify bin + g_return_if_fail (GST_STATE (bin) != GST_STATE_PLAYING); // the element must not already have a parent 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 (bin->children != NULL); - // must be NULL or PAUSED state in order to modify bin - g_return_if_fail ((GST_STATE (bin) == GST_STATE_NULL) || - (GST_STATE (bin) == GST_STATE_PAUSED)); + // must not be in PLAYING state in order to modify bin + g_return_if_fail (GST_STATE (bin) != GST_STATE_PLAYING); // the element must have its parent set to the current bin g_return_if_fail (GST_ELEMENT_PARENT(element) == (GstElement *)bin); diff --git a/gst/gstelement.c b/gst/gstelement.c index a49f72021c..77b68ec46d 100644 --- a/gst/gstelement.c +++ b/gst/gstelement.c @@ -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 (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 */ curpending = GST_STATE(element); @@ -712,6 +715,8 @@ gst_element_set_state (GstElement *element, GstElementState state) /* set the pending state variable */ // FIXME: should probably check to see that we don't already have one 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 */ 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 (GST_IS_ELEMENT (element), GST_STATE_FAILURE); -// g_print("gst_element_change_state(\"%s\",%d)\n", -// element->name,state); + GST_DEBUG (GST_CAT_STATES, "default handler sets '%s' state to %s\n", + GST_ELEMENT_NAME (element), _gst_print_statename(GST_STATE_PENDING(element))); if (GST_STATE_TRANSITION(element) == GST_STATE_READY_TO_PLAYING) GST_SCHEDULE_ENABLE_ELEMENT (element->sched,element); diff --git a/gst/gstpad.c b/gst/gstpad.c index 03cbf0cd35..fc8078e924 100644 --- a/gst/gstpad.c +++ b/gst/gstpad.c @@ -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(realsink), gst_real_pad_signals[REAL_CONNECTED], realsrc); - // now tell the scheduler - GST_SCHEDULE_PAD_CONNECT (realsrc->sched, realsrc, realsink); + // now tell the scheduler(s) + if (realsrc->sched) + 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_DEBUG_PAD_NAME(srcpad), GST_DEBUG_PAD_NAME(sinkpad)); diff --git a/gst/gstscheduler.c b/gst/gstscheduler.c index bd850ab246..e425c15a9c 100644 --- a/gst/gstscheduler.c +++ b/gst/gstscheduler.c @@ -862,6 +862,7 @@ gst_schedule_chain_new (GstSchedule *sched) { GstScheduleChain *chain = g_new (GstScheduleChain, 1); + // initialize the chain with sane values chain->sched = sched; chain->disabled = NULL; chain->elements = NULL; @@ -870,6 +871,7 @@ gst_schedule_chain_new (GstSchedule *sched) chain->cothreaded_elements = 0; chain->schedule = FALSE; + // add the chain to the schedules' list of chains sched->chains = g_list_prepend (sched->chains, chain); sched->num_chains++; @@ -881,11 +883,13 @@ gst_schedule_chain_new (GstSchedule *sched) void 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->num_chains--; - g_list_free (chain->disabled); - g_list_free (chain->elements); + // destroy the chain + g_list_free (chain->disabled); // should be empty... + g_list_free (chain->elements); // ditto g_free (chain); } @@ -925,7 +929,8 @@ gst_schedule_chain_disable_element (GstScheduleChain *chain, GstElement *element chain->disabled = g_list_prepend (chain->disabled, element); // 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 @@ -938,8 +943,13 @@ gst_schedule_chain_remove_element (GstScheduleChain *chain, GstElement *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->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 @@ -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)); 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); } } @@ -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 chain1 = gst_schedule_chain_new (sched); 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 if (gst_schedule_find_chain (sched, element2) == NULL) { // if not in chain, create chain and build from scratch chain2 = gst_schedule_chain_new (sched); 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; GstPad *pad; GstElement *peerelement; + GstScheduleChain *chain; g_return_if_fail (element != NULL); 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_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 sched->elements = g_list_prepend (sched->elements, element); sched->num_elements++; - // set the sched pointer in the element itself - gst_element_set_sched (element, sched); + // create a chain to hold it, and add + chain = gst_schedule_chain_new (sched); + gst_schedule_chain_add_element (chain, element); // set the sched pointer in all the pads pads = element->pads; @@ -1185,6 +1197,8 @@ gst_schedule_disable_element (GstSchedule *sched, GstElement *element) void gst_schedule_remove_element (GstSchedule *sched, GstElement *element) { + GstScheduleChain *chain; + g_return_if_fail (element != NULL); 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_ELEMENT_NAME(element)); - // disable the element, i.e. remove from chain - gst_schedule_disable_element (sched, element); + // find what chain the element is in + chain = gst_schedule_find_chain(sched, element); - // unset the scheduler - gst_element_set_sched (element, NULL); + // disable the element, i.e. remove from chain's active list + 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 sched->elements = g_list_remove (sched->elements, element); 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; gint num_scheduled = 0; gboolean eos = FALSE; + GList *elements; GST_DEBUG_ENTER("(\"%s\")", GST_ELEMENT_NAME (bin)); @@ -1222,7 +1243,8 @@ gst_schedule_iterate (GstSchedule *sched) // step through all the chains chains = sched->chains; - if (chains == NULL) return FALSE; +// if (chains == NULL) return FALSE; +g_return_val_if_fail (chains != NULL, FALSE); while (chains) { chain = (GstScheduleChain *)(chains->data); chains = g_list_next (chains); @@ -1235,8 +1257,17 @@ gst_schedule_iterate (GstSchedule *sched) GST_DEBUG (GST_CAT_DATAFLOW,"starting iteration via cothreads\n"); 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 - entry = GST_ELEMENT (chain->elements->data); +// entry = GST_ELEMENT (chain->elements->data); if (entry) { GST_FLAG_SET (entry, GST_ELEMENT_COTHREAD_STOPPING); GST_DEBUG (GST_CAT_DATAFLOW,"set COTHREAD_STOPPING flag on \"%s\"(@%p)\n", diff --git a/gst/gstscheduler.h b/gst/gstscheduler.h index 6345124e91..b3a1e7b350 100644 --- a/gst/gstscheduler.h +++ b/gst/gstscheduler.h @@ -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_pad_connect (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); -gboolean gst_schedule_iterate (GstSchedule *sched); #ifdef __cplusplus diff --git a/gst/gstthread.c b/gst/gstthread.c index b4c99803bd..a4090ffede 100644 --- a/gst/gstthread.c +++ b/gst/gstthread.c @@ -68,8 +68,7 @@ static GstElementStateReturn gst_thread_change_state (GstElement *element); static xmlNodePtr gst_thread_save_thyself (GstObject *object, xmlNodePtr parent); 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_wait_thread (GstThread *thread, guint syncflag,gboolean set); +static void gst_thread_signal_thread (GstThread *thread, gboolean spinning); static void gst_thread_wait_two_thread (GstThread *thread, guint syncflag, gboolean set,guint syncflag2, gboolean set2); 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_ELEMENT_NAME (GST_ELEMENT (element))); + g_mutex_lock(thread->lock); + // create the thread pthread_create (&thread->thread_id, NULL, gst_thread_main_loop, thread); // wait for it to 'spin up' 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"); } else { 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_DEBUG(0,"sync: telling thread to start spinning\n"); - gst_thread_signal_thread (thread,GST_THREAD_STATE_SPINNING,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); + gst_thread_signal_thread(thread,TRUE); break; case GST_STATE_PLAYING_TO_PAUSED: GST_INFO (GST_CAT_THREAD,"pausing thread \"%s\"", GST_ELEMENT_NAME (GST_ELEMENT (element))); - //GST_FLAG_UNSET(thread,GST_THREAD_STATE_SPINNING); - 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); + gst_thread_signal_thread(thread,FALSE); break; case GST_STATE_PLAYING_TO_READY: - 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); + gst_thread_signal_thread(thread,FALSE); break; case GST_STATE_READY_TO_NULL: GST_INFO (GST_CAT_THREAD,"stopping thread \"%s\"", GST_ELEMENT_NAME (GST_ELEMENT (element))); - //GST_FLAG_SET (thread, GST_THREAD_STATE_REAPING); - gst_thread_signal_thread (thread,GST_THREAD_STATE_REAPING,TRUE); + GST_FLAG_SET (thread, GST_THREAD_STATE_REAPING); + gst_thread_signal_thread(thread,FALSE); 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); 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; default: @@ -330,6 +317,16 @@ gst_thread_change_state (GstElement *element) 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: * @arg: the thread to start @@ -341,8 +338,8 @@ static void * gst_thread_main_loop (void *arg) { GstThread *thread = GST_THREAD (arg); + gboolean first = 1; gint stateset; - gboolean isSpinning = FALSE; GST_INFO (GST_CAT_THREAD,"thread \"%s\" is running with PID %d", GST_ELEMENT_NAME (GST_ELEMENT (thread)), getpid ()); @@ -357,58 +354,48 @@ gst_thread_main_loop (void *arg) if (GST_BIN_CLASS (parent_class)->schedule) GST_BIN_CLASS (parent_class)->schedule (GST_BIN (thread)); - GST_DEBUG(0, "sync: indicating spinup\n"); - gst_thread_signal_thread (thread,GST_THREAD_STATE_STARTED,TRUE); - GST_DEBUG(0, "sync: done indicating spinup\n"); - - GST_INFO (GST_CAT_THREAD,"sync: thread has signaled to parent at startup"); + GST_DEBUG (GST_CAT_THREAD, "sync: indicating spinup\n"); + g_mutex_lock (thread->lock); + g_cond_signal (thread->cond); + // don't unlock the mutex because we hold it into the top of the while loop + GST_DEBUG (GST_CAT_THREAD, "sync: thread has indicated spinup to main process\n"); while (!GST_FLAG_IS_SET (thread, GST_THREAD_STATE_REAPING)) { - if (GST_FLAG_IS_SET (thread, GST_THREAD_STATE_SPINNING)) { - isSpinning=TRUE; + // start out by waiting for a state change into spinning + 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))) { - /*g_mutex_lock(thread->lock); GST_FLAG_UNSET (thread, GST_THREAD_STATE_SPINNING); 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_thread_wait_two_thread (thread,GST_THREAD_STATE_SPINNING,TRUE, - GST_THREAD_STATE_REAPING,TRUE); - GST_DEBUG (0, "sync: done waiting\n"); - isSpinning=TRUE; - // if reaping was returned, break outof while loop - if (GST_FLAG_IS_SET(thread,GST_THREAD_STATE_REAPING)) { - break; - } - - // 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 (GST_CAT_THREAD, "sync: waiting at bottom of while for signal from main process\n"); + g_mutex_lock (thread->lock); + GST_DEBUG (GST_CAT_THREAD, "sync: signaling that the thread is out of the SPINNING loop\n"); + g_cond_signal (thread->cond); + g_cond_wait (thread->cond, thread->lock); + GST_DEBUG (GST_CAT_THREAD, "sync: main process has signaled at bottom of while\n"); + // now change the children's and thread's state + 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"); } + // since we don't unlock at the end of the while loop, do it here + g_mutex_unlock (thread->lock); + GST_INFO (GST_CAT_THREAD, "gstthread: thread \"%s\" is stopped", GST_ELEMENT_NAME (thread)); return NULL; @@ -416,76 +403,27 @@ gst_thread_main_loop (void *arg) // the set flag is to say whether it should set TRUE or FALSE static void -gst_thread_signal_thread (GstThread *thread, guint syncflag, gboolean set) +gst_thread_signal_thread (GstThread *thread, gboolean spinning) { - g_mutex_lock (thread->lock); - GST_DEBUG (0,"sync: signaling thread setting %u to %d\n",syncflag,set); - if (set) - GST_FLAG_SET(thread,syncflag); - else - GST_FLAG_UNSET(thread,syncflag); + // 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); + + if (!spinning) { + GST_DEBUG (GST_CAT_THREAD, "sync-main: waiting for spindown\n"); + g_cond_wait (thread->cond, thread->lock); + } + GST_DEBUG (GST_CAT_THREAD, "sync-main: signaling\n"); g_cond_signal (thread->cond); - g_mutex_unlock (thread->lock); - GST_DEBUG (0,"sync: done signaling thread with %u set to %u..should be %d\n",syncflag, - GST_FLAG_IS_SET(thread,syncflag),set); -} + GST_DEBUG (GST_CAT_THREAD, "sync-main: waiting for ack\n"); + g_cond_wait (thread->cond,thread->lock); -// the set flag is to see what flag to wait for -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); - GST_DEBUG (0, "sync: done waiting for thread for %u to be set %d\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); -// } + GST_DEBUG (GST_CAT_THREAD, "sync-main: unlocking\n"); + g_mutex_unlock(thread->lock); + GST_DEBUG (GST_CAT_THREAD, "sync-main: unlocked\n"); } diff --git a/gstreamer.spec.in b/gstreamer.spec.in index ee35a6ba7f..caa0444785 100644 --- a/gstreamer.spec.in +++ b/gstreamer.spec.in @@ -83,3 +83,4 @@ make prefix=$RPM_BUILD_ROOT%{prefix} install %{prefix}/include/* %{prefix}/lib/lib*.a %{prefix}/lib/lib*.so +%{prefix}/lib/pkgconfig/* diff --git a/tests/incsched.c b/tests/incsched.c index ac394ad7d2..f73b6171d9 100644 --- a/tests/incsched.c +++ b/tests/incsched.c @@ -1,5 +1,3 @@ -<<<<<<< incsched.c -<<<<<<< incsched.c #include #include @@ -49,11 +47,11 @@ int main(int argc,char *argv[]) { g_print("\nAdding sink to bin:\n"); 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"); 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"); 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_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"); gst_element_set_state(GST_ELEMENT(thread),GST_STATE_PLAYING); gst_schedule_show(GST_ELEMENT_SCHED(thread)); diff --git a/tests/threadlock.c b/tests/threadlock.c index a50368c062..f6a4e05387 100644 --- a/tests/threadlock.c +++ b/tests/threadlock.c @@ -12,23 +12,34 @@ int main(int argc,char *argv[]) { pipeline = gst_pipeline_new("pipeline"); thread = gst_thread_new("thread"); src = gst_elementfactory_make("fakesrc","src"); - queue1 = gst_elementfactory_make("queue","queue"); sink = gst_elementfactory_make("fakesink","sink"); - gst_bin_add(pipeline,src); - gst_bin_add(pipeline,queue1); - gst_bin_add(pipeline,GST_ELEMENT(thread)); + fprintf(stderr,"ADDING src\n"); + gst_bin_add(thread,src); + fprintf(stderr,"ADDING sink\n"); 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"); - gst_element_connect (queue1, "src", thread, "sink"); + fprintf(stderr,"CONNECTING src to sink\n"); + gst_element_connect (src, "src", sink, "sink"); - while (1) { - fprintf(stderr,"SWITCHING TO READY:\n"); - gst_element_set_state (pipeline, GST_STATE_READY); - fprintf(stderr,"SWITCHING TO NULL:\n"); - gst_element_set_state (pipeline, GST_STATE_NULL); - } + 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)); + +/* + 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)); +*/ } diff --git a/tools/gstreamer-launch.c b/tools/gstreamer-launch.c index 82a8d234a5..1938f2bfe5 100644 --- a/tools/gstreamer-launch.c +++ b/tools/gstreamer-launch.c @@ -25,6 +25,11 @@ main(int argc, char *argv[]) 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"); gst_element_set_state (pipeline, GST_STATE_PLAYING);