More eos handling, bin in bin is handled correctly now.

Original commit message from CVS:
More eos handling, bin in bin is handled correctly now.
Updated gstreamer-launch to loop while !EOS.
This commit is contained in:
Wim Taymans 2001-01-21 16:06:42 +00:00
parent 3dd77c5107
commit 044c4611af
9 changed files with 136 additions and 95 deletions

View file

@ -136,6 +136,7 @@ gst_bin_init (GstBin *bin)
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;
}
@ -250,6 +251,22 @@ gst_bin_change_state (GstElement *element)
// 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) {
@ -271,21 +288,6 @@ gst_bin_change_state (GstElement *element)
}
// 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);
}
@ -551,9 +553,12 @@ gst_bin_received_eos (GstElement *element, GstBin *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);
}
/**
@ -610,6 +615,7 @@ gst_bin_create_plan_func (GstBin *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
@ -635,8 +641,11 @@ gst_bin_create_plan_func (GstBin *bin)
// 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);
@ -701,10 +710,6 @@ gst_bin_create_plan_func (GstBin *bin)
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);
@ -712,6 +717,12 @@ gst_bin_create_plan_func (GstBin *bin)
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);
@ -719,6 +730,10 @@ gst_bin_create_plan_func (GstBin *bin)
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)));
}
@ -795,15 +810,20 @@ gst_bin_iterate_func (GstBin *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)));

View file

@ -67,6 +67,7 @@ struct _GstBin {
GList *children;
gint num_eos_providers;
GList *eos_providers;
GCond *eoscond;
/* iteration state */
gboolean need_cothreads;

View file

@ -202,7 +202,7 @@ gst_element_add_ghost_pad (GstElement *element, GstPad *pad, gchar *name)
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));

View file

@ -34,7 +34,7 @@ GstElementDetails gst_thread_details = {
"Container that creates/manages a thread",
VERSION,
"Erik Walthinsen <omega@cse.ogi.edu>",
"(C) 1999",
"(C) 1999, 2000",
};
@ -50,21 +50,22 @@ enum {
};
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);
@ -92,36 +93,37 @@ gst_thread_get_type(void) {
}
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)));
@ -136,19 +138,28 @@ gst_thread_init (GstThread *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))
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))
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));
@ -170,10 +181,10 @@ gst_thread_set_arg (GtkObject *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));
@ -197,15 +208,15 @@ gst_thread_get_arg (GtkObject *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;
@ -217,7 +228,7 @@ gst_thread_change_state (GstElement *element)
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);
@ -229,8 +240,8 @@ gst_thread_change_state (GstElement *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) {
@ -268,18 +279,18 @@ gst_thread_change_state (GstElement *element)
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;
@ -298,7 +309,7 @@ gst_thread_change_state (GstElement *element)
* 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);
@ -306,8 +317,9 @@ gst_thread_main_loop (void *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)) {
@ -323,7 +335,7 @@ gst_thread_main_loop (void *arg)
}
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)));

View file

@ -63,6 +63,11 @@ GstVideoScale *gst_videoscale_new(gint sw, gint sh, gint dw, gint dh, GstColorSp
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);

View file

@ -1,4 +1,4 @@
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)

View file

@ -19,7 +19,7 @@ eos_signal (GstElement *element)
int
main(int argc,char *argv[])
{
GstBin *pipeline, *pipeline2;
GstBin *pipeline, *bin;
GstElement *src,*identity,*sink;
GstElement *src2,*identity2,*sink2;
@ -38,14 +38,14 @@ main(int argc,char *argv[])
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");

View file

@ -29,10 +29,11 @@ main(int argc,char *argv[])
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");
@ -51,7 +52,7 @@ main(int argc,char *argv[])
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");

View file

@ -4,31 +4,33 @@
#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 (1)
gst_bin_iterate (GST_BIN (pipeline));
while (gst_bin_iterate (GST_BIN (pipeline)));
gst_element_set_state (pipeline, GST_STATE_NULL);
return 0;
}