bin->eos_providers = NULL;
bin->num_eos_providers = 0;
bin->chains = NULL;
+ bin->eoscond = g_cond_new ();
// FIXME temporary testing measure
// bin->use_cothreads = TRUE;
}
// g_return_val_if_fail(bin->numchildren != 0, GST_STATE_FAILURE);
+ switch (GST_STATE_TRANSITION (element)) {
+ case GST_STATE_NULL_TO_READY:
+ {
+ GstObject *parent;
+
+ parent = gst_object_get_parent (GST_OBJECT (element));
+
+ if (!parent || !GST_IS_BIN (parent))
+ gst_bin_create_plan (bin);
+
+ break;
+ }
+ default:
+ break;
+ }
+
// g_print("-->\n");
children = bin->children;
while (children) {
}
// g_print("<-- \"%s\"\n",gst_object_get_name(GST_OBJECT(bin)));
- switch (GST_STATE_TRANSITION (element)) {
- case GST_STATE_NULL_TO_READY:
- {
- GstObject *parent;
-
- parent = gst_object_get_parent (GST_OBJECT (element));
-
- if (!parent || !GST_IS_BIN (parent))
- gst_bin_create_plan (bin);
-
- break;
- }
- default:
- break;
- }
return gst_bin_change_state_norecurse (bin);
}
GST_INFO_ELEMENT (GST_CAT_PLANNING, bin, "child %s fired eos, pending %d\n", gst_element_get_name (element),
bin->num_eos_providers);
+ GST_LOCK (bin);
if (bin->num_eos_providers) {
bin->num_eos_providers--;
+ g_cond_signal (bin->eoscond);
}
+ GST_UNLOCK (bin);
}
/**
}
GST_DEBUG (0,"setting manager to \"%s\"\n", gst_element_get_name (manager));
}
+ gst_element_set_manager (GST_ELEMENT (bin), manager);
// perform the first recursive pass of plan generation
// we set the manager of every element but those who manage themselves
// we do recursion and such for Bins
if (GST_IS_BIN (element)) {
// recurse into the child Bin
- GST_DEBUG (0,"recursing into child Bin \"%s\"\n",elementname);
+ GST_DEBUG (0,"recursing into child Bin \"%s\" with manager \"%s\"\n",elementname,
+ gst_element_get_name(element->manager));
gst_bin_create_plan (GST_BIN (element));
+ GST_DEBUG (0,"after recurse got manager \"%s\"\n",
+ gst_element_get_name(element->manager));
// check to see if it needs cothreads and isn't self-managing
if (((GST_BIN (element))->need_cothreads) && !GST_FLAG_IS_SET(element,GST_BIN_FLAG_MANAGER)) {
GST_DEBUG (0,"requiring cothreads because child bin \"%s\" does\n",elementname);
GST_DEBUG (0,"flattened recurse into \"%s\"\n",elementname);
pending = g_slist_prepend (pending, element);
- gtk_signal_connect (GTK_OBJECT (element), "eos", gst_bin_received_eos, bin);
- bin->eos_providers = g_list_prepend (bin->eos_providers, element);
- bin->num_eos_providers++;
-
// otherwise add it to the list of elements
} else {
GST_DEBUG (0,"found element \"%s\" that I manage\n",elementname);
bin->num_managed_elements++;
}
}
+ // else it's not ours and we need to wait for EOS notifications
+ else {
+ gtk_signal_connect (GTK_OBJECT (element), "eos", gst_bin_received_eos, bin);
+ bin->eos_providers = g_list_prepend (bin->eos_providers, element);
+ bin->num_eos_providers++;
+ }
}
} while (pending);
gst_bin_schedule(bin);
+ g_print ("gstbin \"%s\", eos providers:%d\n",
+ gst_element_get_name (GST_ELEMENT (bin)),
+ bin->num_eos_providers);
+
GST_DEBUG_LEAVE("(\"%s\")",gst_element_get_name(GST_ELEMENT(bin)));
}
num_scheduled++;
}
- /*
- g_print ("bin \"%s\", eos providers:%d, scheduled: %d\n",
- gst_element_get_name (GST_ELEMENT (bin)),
- bin->num_eos_providers, num_scheduled);
- */
-
- if (!num_scheduled && !bin->num_eos_providers) {
- gst_element_signal_eos (GST_ELEMENT (bin));
- eos = TRUE;
+ // check if nothing was scheduled that was ours..
+ if (!num_scheduled) {
+ // are there any other elements that are still busy?
+ if (bin->num_eos_providers) {
+ GST_LOCK (bin);
+ GST_DEBUG (0,"waiting for eos providers\n");
+ g_cond_wait (bin->eoscond, GST_OBJECT(bin)->lock);
+ GST_DEBUG (0,"num eos providers %d\n", bin->num_eos_providers);
+ GST_UNLOCK (bin);
+ }
+ else {
+ gst_element_signal_eos (GST_ELEMENT (bin));
+ eos = TRUE;
+ }
}
GST_DEBUG_LEAVE("(%s)", gst_element_get_name (GST_ELEMENT (bin)));
GList *children;
gint num_eos_providers;
GList *eos_providers;
+ GCond *eoscond;
/* iteration state */
gboolean need_cothreads;
element->pads = g_list_append (element->pads, ghostpad);
element->numpads++;
// set the parent of the ghostpad
- gst_pad_set_parent(ghostpad,element);
+ gst_pad_set_parent(ghostpad, GST_OBJECT (element));
GST_DEBUG(0,"added ghostpad %s:%s\n",GST_DEBUG_PAD_NAME(ghostpad));
"Container that creates/manages a thread",
VERSION,
"Erik Walthinsen <omega@cse.ogi.edu>",
- "(C) 1999",
+ "(C) 1999, 2000",
};
};
-static void gst_thread_class_init (GstThreadClass *klass);
-static void gst_thread_init (GstThread *thread);
+static void gst_thread_class_init (GstThreadClass *klass);
+static void gst_thread_init (GstThread *thread);
-static void gst_thread_set_arg (GtkObject *object,GtkArg *arg,guint id);
-static void gst_thread_get_arg (GtkObject *object,GtkArg *arg,guint id);
+static void gst_thread_set_arg (GtkObject *object,GtkArg *arg,guint id);
+static void gst_thread_get_arg (GtkObject *object,GtkArg *arg,guint id);
-static GstElementStateReturn gst_thread_change_state (GstElement *element);
+static GstElementStateReturn gst_thread_change_state (GstElement *element);
-static xmlNodePtr gst_thread_save_thyself (GstElement *element,xmlNodePtr parent);
-static void gst_thread_restore_thyself (GstElement *element,xmlNodePtr parent,
+static xmlNodePtr gst_thread_save_thyself (GstElement *element,xmlNodePtr parent);
+static void gst_thread_restore_thyself (GstElement *element,xmlNodePtr parent,
GHashTable *elements);
-static void gst_thread_signal_thread (GstThread *thread);
-static void gst_thread_wait_thread (GstThread *thread);
-static void gst_thread_create_plan_dummy (GstBin *bin);
+static void gst_thread_signal_thread (GstThread *thread);
+static void gst_thread_wait_thread (GstThread *thread);
+static void gst_thread_create_plan_dummy (GstBin *bin);
+static void gst_thread_schedule_dummy (GstBin *bin);
static void* gst_thread_main_loop (void *arg);
}
static void
-gst_thread_class_init (GstThreadClass *klass)
+gst_thread_class_init (GstThreadClass *klass)
{
GtkObjectClass *gtkobject_class;
GstObjectClass *gstobject_class;
GstElementClass *gstelement_class;
GstBinClass *gstbin_class;
- gtkobject_class = (GtkObjectClass*)klass;
- gstobject_class = (GstObjectClass*)klass;
- gstelement_class = (GstElementClass*)klass;
- gstbin_class = (GstBinClass*)klass;
+ gtkobject_class = (GtkObjectClass*)klass;
+ gstobject_class = (GstObjectClass*)klass;
+ gstelement_class = (GstElementClass*)klass;
+ gstbin_class = (GstBinClass*)klass;
parent_class = gtk_type_class (GST_TYPE_BIN);
gtk_object_add_arg_type ("GstThread::create_thread", GTK_TYPE_BOOL,
GTK_ARG_READWRITE, ARG_CREATE_THREAD);
- gstelement_class->change_state = gst_thread_change_state;
- gstelement_class->save_thyself = gst_thread_save_thyself;
- gstelement_class->restore_thyself = gst_thread_restore_thyself;
+ gstelement_class->change_state = gst_thread_change_state;
+ gstelement_class->save_thyself = gst_thread_save_thyself;
+ gstelement_class->restore_thyself = gst_thread_restore_thyself;
- gstbin_class->create_plan = gst_thread_create_plan_dummy;
+ //gstbin_class->create_plan = gst_thread_create_plan_dummy;
+ gstbin_class->schedule = gst_thread_schedule_dummy;
gtkobject_class->set_arg = gst_thread_set_arg;
gtkobject_class->get_arg = gst_thread_get_arg;
}
-static void
-gst_thread_init (GstThread *thread)
+static void
+gst_thread_init (GstThread *thread)
{
GST_DEBUG (0,"initializing thread '%s'\n",gst_element_get_name(GST_ELEMENT(thread)));
thread->cond = g_cond_new();
}
-static void
-gst_thread_create_plan_dummy (GstBin *bin)
+static void
+gst_thread_schedule_dummy (GstBin *bin)
+{
+ g_return_if_fail (GST_IS_THREAD (bin));
+
+ if (!GST_FLAG_IS_SET (GST_THREAD (bin), GST_THREAD_STATE_SPINNING))
+ GST_INFO (GST_CAT_THREAD,"gstthread: scheduling delayed until thread starts");
+}
+
+static void
+gst_thread_create_plan_dummy (GstBin *bin)
{
g_return_if_fail (GST_IS_THREAD (bin));
- if (!GST_FLAG_IS_SET (GST_THREAD (bin), GST_THREAD_STATE_SPINNING))
+ if (!GST_FLAG_IS_SET (GST_THREAD (bin), GST_THREAD_STATE_SPINNING))
GST_INFO (GST_CAT_THREAD,"gstthread: create plan delayed until thread starts");
}
-static void
+static void
gst_thread_set_arg (GtkObject *object,
GtkArg *arg,
- guint id)
+ guint id)
{
/* it's not null if we got it, but it might not be ours */
g_return_if_fail (GST_IS_THREAD (object));
}
}
-static void
+static void
gst_thread_get_arg (GtkObject *object,
GtkArg *arg,
- guint id)
+ guint id)
{
/* it's not null if we got it, but it might not be ours */
g_return_if_fail (GST_IS_THREAD (object));
* Returns: The new thread
*/
GstElement*
-gst_thread_new (guchar *name)
+gst_thread_new (guchar *name)
{
return gst_elementfactory_make ("thread", name);
}
-static GstElementStateReturn
-gst_thread_change_state (GstElement *element)
+static GstElementStateReturn
+gst_thread_change_state (GstElement *element)
{
GstThread *thread;
gboolean stateset = GST_STATE_SUCCESS;
thread = GST_THREAD (element);
GST_INFO (GST_CAT_THREAD,"gstthread: thread \"%s\" change state %d",
- gst_element_get_name (GST_ELEMENT (element)),
+ gst_element_get_name (GST_ELEMENT (element)),
GST_STATE_PENDING (element));
pending = GST_STATE_PENDING (element);
if (GST_ELEMENT_CLASS (parent_class)->change_state)
stateset = GST_ELEMENT_CLASS (parent_class)->change_state (element);
-
- GST_INFO (GST_CAT_THREAD, "gstthread: stateset %d %d %d %02x", GST_STATE (element), stateset,
+
+ GST_INFO (GST_CAT_THREAD, "gstthread: stateset %d %d %d %02x", GST_STATE (element), stateset,
GST_STATE_PENDING (element), GST_STATE_TRANSITION (element));
switch (transition) {
GST_FLAG_SET (thread, GST_THREAD_STATE_SPINNING);
gst_thread_signal_thread (thread);
- break;
+ break;
case GST_STATE_PLAYING_TO_PAUSED:
GST_INFO (GST_CAT_THREAD,"gstthread: pausing thread \"%s\"",
gst_element_get_name (GST_ELEMENT (element)));
-
+
//GST_FLAG_UNSET(thread,GST_THREAD_STATE_SPINNING);
gst_thread_signal_thread (thread);
break;
case GST_STATE_READY_TO_NULL:
GST_INFO (GST_CAT_THREAD,"gstthread: stopping thread \"%s\"",
gst_element_get_name (GST_ELEMENT (element)));
-
+
GST_FLAG_SET (thread, GST_THREAD_STATE_REAPING);
gst_thread_signal_thread (thread);
break;
* while the state is GST_THREAD_STATE_SPINNING
*/
static void *
-gst_thread_main_loop (void *arg)
+gst_thread_main_loop (void *arg)
{
GstThread *thread = GST_THREAD (arg);
gst_element_get_name (GST_ELEMENT (thread)), getpid ());
// construct the plan and signal back
- if (GST_BIN_CLASS (parent_class)->create_plan)
- GST_BIN_CLASS (parent_class)->create_plan (GST_BIN (thread));
+ if (GST_BIN_CLASS (parent_class)->schedule)
+ GST_BIN_CLASS (parent_class)->schedule (GST_BIN (thread));
+
gst_thread_signal_thread (thread);
while (!GST_FLAG_IS_SET (thread, GST_THREAD_STATE_REAPING)) {
}
GST_FLAG_UNSET (thread, GST_THREAD_STATE_REAPING);
-// pthread_join (thread->thread_id, 0);
+ //pthread_join (thread->thread_id, 0);
GST_INFO (GST_CAT_THREAD, "gstthread: thread \"%s\" is stopped",
gst_element_get_name (GST_ELEMENT (thread)));
new->scale = gst_videoscale_scale_rgb;
scale_bytes = 2;
break;
+ case GST_COLORSPACE_RGB32:
+ case GST_COLORSPACE_BGR32:
+ new->scale = gst_videoscale_scale_rgb;
+ scale_bytes = 4;
+ break;
default:
g_print("videoscale: unsupported video format %d\n", format);
g_free(new);
-noinst_PROGRAMS = case1 case2 case3 case4 case5 case6
+noinst_PROGRAMS = case1 case2 case3 case4 case5 case6 case7
# jsut apps here, this is safe
LIBS += $(GST_LIBS)
int
main(int argc,char *argv[])
{
- GstBin *pipeline, *pipeline2;
+ GstBin *pipeline, *bin;
GstElement *src,*identity,*sink;
GstElement *src2,*identity2,*sink2;
sink = gst_elementfactory_make("fakesink","sink");
g_return_val_if_fail(sink != NULL, 4);
- pipeline2 = GST_BIN(gst_pipeline_new("pipeline2"));
- g_return_val_if_fail(pipeline2 != NULL, 1);
+ bin = GST_BIN(gst_bin_new("bin"));
+ g_return_val_if_fail(bin != NULL, 1);
- gst_bin_add(pipeline2,GST_ELEMENT(src));
- gst_bin_add(pipeline2,GST_ELEMENT(identity));
- gst_bin_add(pipeline2,GST_ELEMENT(sink));
+ gst_bin_add(bin,GST_ELEMENT(src));
+ gst_bin_add(bin,GST_ELEMENT(identity));
+ gst_bin_add(bin,GST_ELEMENT(sink));
- gst_bin_add(pipeline,GST_ELEMENT(pipeline2));
+ gst_bin_add(pipeline,GST_ELEMENT(bin));
gst_element_connect(src,"src",identity,"sink");
gst_element_connect(identity,"src",sink,"sink");
g_return_val_if_fail(pipeline != NULL, 1);
src = gst_elementfactory_make("fakesrc","src");
- gtk_object_set (GTK_OBJECT (src), "num_buffers", 1, NULL);
+ gtk_object_set (GTK_OBJECT (src), "num_buffers", 4, NULL);
g_return_val_if_fail(src != NULL, 2);
identity = gst_elementfactory_make("identity","identity");
+ gtk_object_set (GTK_OBJECT (identity), "sleep_time", 1000000, NULL);
g_return_val_if_fail(identity != NULL, 3);
sink = gst_elementfactory_make("fakesink","sink");
gst_element_connect(identity,"src",sink,"sink");
src2 = gst_elementfactory_make("fakesrc","src2");
- gtk_object_set (GTK_OBJECT (src2), "num_buffers", 4, NULL);
+ gtk_object_set (GTK_OBJECT (src2), "num_buffers", 1, NULL);
g_return_val_if_fail(src2 != NULL, 2);
identity2 = gst_elementfactory_make("identity","identity2");
#include <string.h>
#include <stdlib.h>
-int main(int argc,char *argv[]) {
+int
+main(int argc, char *argv[])
+{
GstElement *pipeline;
char **argvn;
gchar *cmdline;
- int i;
-
- gst_init(&argc,&argv);
- pipeline = gst_pipeline_new("launch");
+ gst_init (&argc, &argv);
+
+ pipeline = gst_pipeline_new ("launch");
// make a null-terminated version of argv
- argvn = g_new0(char *,argc);
- memcpy(argvn,argv+1,sizeof(char*)*(argc-1));
+ argvn = g_new0 (char *,argc);
+ memcpy (argvn, argv+1, sizeof (char*) * (argc-1));
// join the argvs together
- cmdline = g_strjoinv(" ",argvn);
+ cmdline = g_strjoinv (" ", argvn);
// free the null-terminated argv
- g_free(argvn);
+ g_free (argvn);
- gst_parse_launch(cmdline,pipeline);
+ gst_parse_launch (cmdline, GST_BIN (pipeline));
fprintf(stderr,"RUNNING pipeline\n");
- gst_element_set_state(pipeline,GST_STATE_PLAYING);
+ gst_element_set_state (pipeline, GST_STATE_PLAYING);
+
+ while (gst_bin_iterate (GST_BIN (pipeline)));
- while (1)
- gst_bin_iterate (GST_BIN (pipeline));
+ gst_element_set_state (pipeline, GST_STATE_NULL);
return 0;
}