From: Wim Taymans Date: Sun, 17 Sep 2000 22:08:09 +0000 (+0000) Subject: Added gst_pipeline_add_sink/src to allow multiple sink cases and more complex autoplu... X-Git-Tag: RELEASE-0_1_0-SLIPSTREAM~313 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=cab1728fa5774bf1873b9530465daaa36c854b46;p=platform%2Fupstream%2Fgstreamer.git Added gst_pipeline_add_sink/src to allow multiple sink cases and more complex autoplugging. Update docs too. Original commit message from CVS: Added gst_pipeline_add_sink/src to allow multiple sink cases and more complex autoplugging. Update docs too. Simplified the pipeline autoplugging code. Changed the cothread case: One iteration is now a push from the src element. The disk source does not change its state anymore on eof. Better type setting for the ac3 parser/decoder and mpeg2parse. --- diff --git a/docs/gst/gstreamer-decl.txt b/docs/gst/gstreamer-decl.txt index f51edaa..ac1fda3 100644 --- a/docs/gst/gstreamer-decl.txt +++ b/docs/gst/gstreamer-decl.txt @@ -1328,6 +1328,9 @@ extern GstElementDetails gst_pipeline_details; GstPipeline struct GstPipeline { GstBin bin; + + GstElement *src; // we only allow one src element + GList *sinks; // and multiple sinks }; @@ -1356,6 +1359,16 @@ guchar *name GstPipeline *pipeline +gst_pipeline_add_src +void +GstPipeline *pipeline, GstElement *src + + +gst_pipeline_add_sink +void +GstPipeline *pipeline, GstElement *sink + + gst_pipeline_iterate void GstPipeline *pipeline @@ -2067,6 +2080,36 @@ GstBufferPool *pool +GET_SP +#define GET_SP(target) \ + __asm__("movl %%esp, %0" : "=m"(target) : : "esp", "ebp"); + + +SET_SP +#define SET_SP(source) \ + __asm__("movl %0, %%esp\n" : "=m"(thread->sp)); + + +JUMP +#define JUMP(target) \ + __asm__("jmp " SYMBOL_NAME_STR(cothread_stub)) + + +GET_SP +#define GET_SP(target) \ + __asm__("stw 1,%0" : "=m"(target) : : "r1"); + + +SET_SP +#define SET_SP(source) \ + __asm__("lwz 1,%0" : "=m"(source)) + + +JUMP +#define JUMP(target) \ + __asm__("b " SYMBOL_NAME_STR(cothread_stub)) + + GST_TYPE_ASYNCDISKSRC #define GST_TYPE_ASYNCDISKSRC \ (gst_asyncdisksrc_get_type()) diff --git a/docs/gst/gstreamer-sections.txt b/docs/gst/gstreamer-sections.txt index 3b71aca..801a75a 100644 --- a/docs/gst/gstreamer-sections.txt +++ b/docs/gst/gstreamer-sections.txt @@ -16,6 +16,9 @@ cothread_setfunc cothread_switch cothread_main +GET_SP +JUMP +SET_SP
@@ -297,6 +300,8 @@ gst_pad_get_type GstPipeline GstPipeline gst_pipeline_new +gst_pipeline_add_sink +gst_pipeline_add_src gst_pipeline_autoplug gst_pipeline_destroy gst_pipeline_iterate diff --git a/docs/gst/tmpl/gstpipeline.sgml b/docs/gst/tmpl/gstpipeline.sgml index be25145..17bcd0b 100644 --- a/docs/gst/tmpl/gstpipeline.sgml +++ b/docs/gst/tmpl/gstpipeline.sgml @@ -36,6 +36,24 @@ pipeline figure out what plugins to use. @Returns: + + + + + +@pipeline: +@sink: + + + + + + + +@pipeline: +@src: + + diff --git a/docs/manual/helloworld2.sgml b/docs/manual/helloworld2.sgml index 7fd7c80..b1d1782 100644 --- a/docs/manual/helloworld2.sgml +++ b/docs/manual/helloworld2.sgml @@ -58,8 +58,8 @@ int main(int argc,char *argv[]) audiosink = gst_elementfactory_make("audiosink", "play_audio"); /* add objects to the main pipeline */ - gst_bin_add(GST_BIN(pipeline), disksrc); - gst_bin_add(GST_BIN(pipeline), audiosink); + gst_pipeline_add_src(GST_PIPELINE(pipeline), disksrc); + gst_pipeline_add_sink(GST_PIPELINE(pipeline), audiosink); if (!gst_pipeline_autoplug(GST_PIPELINE(pipeline))) { g_print("unable to handle stream\n"); @@ -118,7 +118,7 @@ int main(int argc,char *argv[]) - The source and the sink elements will be found inside the pipeline + The pipeline will try to connect the src and the sink element. diff --git a/examples/helloworld2/helloworld2.c b/examples/helloworld2/helloworld2.c index 2405310..f687ef6 100644 --- a/examples/helloworld2/helloworld2.c +++ b/examples/helloworld2/helloworld2.c @@ -38,8 +38,8 @@ int main(int argc,char *argv[]) g_assert(audiosink != NULL); /* add objects to the main pipeline */ - gst_bin_add(GST_BIN(pipeline), disksrc); - gst_bin_add(GST_BIN(pipeline), audiosink); + gst_pipeline_add_src(GST_PIPELINE(pipeline), disksrc); + gst_pipeline_add_sink(GST_PIPELINE(pipeline), audiosink); if (!gst_pipeline_autoplug(GST_PIPELINE(pipeline))) { g_print("unable to handle stream\n"); diff --git a/examples/thread/thread.c b/examples/thread/thread.c index 1635219..4d8073d 100644 --- a/examples/thread/thread.c +++ b/examples/thread/thread.c @@ -45,8 +45,8 @@ int main(int argc,char *argv[]) g_assert(audiosink != NULL); /* add objects to the main pipeline */ - gst_bin_add(GST_BIN(pipeline), disksrc); - gst_bin_add(GST_BIN(pipeline), audiosink); + gst_pipeline_add_src(GST_PIPELINE(pipeline), disksrc); + gst_pipeline_add_sink(GST_PIPELINE(pipeline), audiosink); if (!gst_pipeline_autoplug(GST_PIPELINE(pipeline))) { g_print("unable to handle stream\n"); diff --git a/gst/Makefile.am b/gst/Makefile.am index e2e8d4b..f0ab122 100644 --- a/gst/Makefile.am +++ b/gst/Makefile.am @@ -55,9 +55,6 @@ libgstinclude_HEADERS = \ gstbufferpool.h \ gstclock.h \ gstcpu.h \ - gstarch.h \ - gsti386.h \ - gstppc.h \ gstelement.h \ gstbin.h \ gstpipeline.h \ @@ -75,6 +72,11 @@ libgstinclude_HEADERS = \ gstxml.h \ cothreads.h +noinst_HEADERS = \ + gstarch.h \ + gsti386.h \ + gstppc.h + CFLAGS += -O2 -Wall libgst_la_LIBADD = $(GLIB_LIBS) $(GTK_LIBS) $(XML_LIBS) diff --git a/gst/cothreads.c b/gst/cothreads.c index d14a219..7d422c8 100644 --- a/gst/cothreads.c +++ b/gst/cothreads.c @@ -124,10 +124,12 @@ void cothread_switch(cothread_state *thread) { exit(2); } + /* if (current == thread) { g_print("cothread: trying to switch to same thread, legal but not necessary\n"); - return; + //return; } + */ // find the number of the thread to switch to ctx->current = thread->threadnum; @@ -150,10 +152,10 @@ void cothread_switch(cothread_state *thread) { // switch to it longjmp(thread->jmp,1); } else { - DEBUG("cothread: exit thread \n"); SET_SP(thread->sp); // start it //JUMP(cothread_stub); cothread_stub(); + DEBUG("cothread: exit thread \n"); } } diff --git a/gst/elements/gstdisksrc.c b/gst/elements/gstdisksrc.c index ea77836..d12ad9b 100644 --- a/gst/elements/gstdisksrc.c +++ b/gst/elements/gstdisksrc.c @@ -221,7 +221,6 @@ void gst_disksrc_push(GstSrc *src) { else if (readbytes == 0) { gst_src_signal_eos(GST_SRC(disksrc)); gst_buffer_unref(buf); - GST_STATE(src) = GST_STATE_PAUSED; return; } diff --git a/gst/gstbin.c b/gst/gstbin.c index 3f1a1a0..b2748c0 100644 --- a/gst/gstbin.c +++ b/gst/gstbin.c @@ -441,10 +441,9 @@ static int gst_bin_loopfunc_wrapper(int argc,char *argv[]) { DEBUG("** gst_bin_loopfunc_wrapper(): element is chain-based, calling in infinite loop\n"); if (GST_IS_SRC(element)) { //while (1) { - while (GST_STATE(element) == GST_STATE_PLAYING) { DEBUG("** gst_bin_loopfunc_wrapper(): calling push function of source\n"); gst_src_push(GST_SRC(element)); - } + //} } else { while (1) { pads = element->pads; @@ -625,8 +624,8 @@ void gst_bin_iterate_func(GstBin *bin) { if (bin->need_cothreads) { // all we really have to do is switch to the first child // FIXME this should be lots more intelligent about where to start - //g_print("** in gst_bin_iterate_func()==================================%s\n", - // gst_element_get_name(GST_ELEMENT(bin->children->data))); + DEBUG("** in gst_bin_iterate_func()==================================%s\n", + gst_element_get_name(GST_ELEMENT(bin->children->data))); cothread_switch(GST_ELEMENT(bin->children->data)->threadstate); } else { entries = bin->entries; diff --git a/gst/gstpipeline.c b/gst/gstpipeline.c index f94c7c0..adcc010 100644 --- a/gst/gstpipeline.c +++ b/gst/gstpipeline.c @@ -91,6 +91,8 @@ gst_pipeline_class_init(GstPipelineClass *klass) { } static void gst_pipeline_init(GstPipeline *pipeline) { + pipeline->src = NULL; + pipeline->sinks = NULL; } @@ -111,7 +113,8 @@ GstElement *gst_pipeline_new(guchar *name) { } static void gst_pipeline_prepare(GstPipeline *pipeline) { - g_print("GstPipeline: preparing pipeline \"%s\" for playing\n", gst_element_get_name(GST_ELEMENT(pipeline))); + g_print("GstPipeline: preparing pipeline \"%s\" for playing\n", + gst_element_get_name(GST_ELEMENT(pipeline))); } static void gst_pipeline_have_type(GstSink *sink, GstSink *sink2, gpointer data) { @@ -125,7 +128,8 @@ static guint16 gst_pipeline_typefind(GstPipeline *pipeline, GstElement *element) GstElement *typefind; guint16 type_id = 0; - g_print("GstPipeline: typefind for element \"%s\" %p\n", gst_element_get_name(element), &found); + g_print("GstPipeline: typefind for element \"%s\" %p\n", + gst_element_get_name(element), &found); typefind = gst_elementfactory_make("typefind","typefind"); g_return_val_if_fail(typefind != NULL, FALSE); @@ -142,6 +146,7 @@ static guint16 gst_pipeline_typefind(GstPipeline *pipeline, GstElement *element) gst_element_set_state(GST_ELEMENT(element),GST_STATE_READY); gst_element_set_state(GST_ELEMENT(element),GST_STATE_PLAYING); + // keep pushing buffers... the have_type signal handler will set the found flag while (!found) { gst_src_push(GST_SRC(element)); } @@ -150,10 +155,9 @@ static guint16 gst_pipeline_typefind(GstPipeline *pipeline, GstElement *element) if (found) { type_id = gst_util_get_int_arg(GTK_OBJECT(typefind),"type"); + gst_pad_set_type_id(gst_element_get_pad(element, "src"), type_id); } - gst_pad_set_type_id(gst_element_get_pad(element, "src"), type_id); - gst_pad_disconnect(gst_element_get_pad(element,"src"), gst_element_get_pad(typefind,"sink")); gst_bin_remove(GST_BIN(pipeline), typefind); @@ -165,6 +169,7 @@ static guint16 gst_pipeline_typefind(GstPipeline *pipeline, GstElement *element) static void gst_pipeline_pads_autoplug_func(GstElement *src, GstPad *pad, GstElement *sink) { GList *sinkpads; GstPad *sinkpad; + gboolean connected = FALSE; g_print("gstpipeline: autoplug pad connect function type %d\n", pad->type); @@ -173,14 +178,24 @@ static void gst_pipeline_pads_autoplug_func(GstElement *src, GstPad *pad, GstEle sinkpad = (GstPad *)sinkpads->data; // if we have a match, connect the pads - if (sinkpad->type == pad->type && sinkpad->direction == GST_PAD_SINK && !GST_PAD_CONNECTED(sinkpad)) { + if (sinkpad->type == pad->type && + sinkpad->direction == GST_PAD_SINK && + !GST_PAD_CONNECTED(sinkpad)) + { gst_pad_connect(pad, sinkpad); - g_print("gstpipeline: autoconnect pad \"%s\" (%d) in element %s <-> ", pad->name, pad->type, gst_element_get_name(src)); - g_print("pad \"%s\" (%d) in element %s\n", sinkpad->name, sinkpad->type, gst_element_get_name(sink)); + g_print("gstpipeline: autoconnect pad \"%s\" (%d) in element %s <-> ", pad->name, + pad->type, gst_element_get_name(src)); + g_print("pad \"%s\" (%d) in element %s\n", sinkpad->name, sinkpad->type, + gst_element_get_name(sink)); + connected = TRUE; break; } sinkpads = g_list_next(sinkpads); } + + if (!connected) { + g_print("gstpipeline: no path to sinks for type %d\n", pad->type); + } } static void gst_pipeline_pads_autoplug(GstElement *src, GstElement *sink) { @@ -201,10 +216,14 @@ static void gst_pipeline_pads_autoplug(GstElement *src, GstElement *sink) { sinkpad = (GstPad *)sinkpads->data; // if we have a match, connect the pads - if (sinkpad->type == srcpad->type && sinkpad->direction == GST_PAD_SINK && !GST_PAD_CONNECTED(sinkpad)) { + if (sinkpad->type == srcpad->type && + sinkpad->direction == GST_PAD_SINK && + !GST_PAD_CONNECTED(sinkpad)) { gst_pad_connect(srcpad, sinkpad); - g_print("gstpipeline: autoconnect pad \"%s\" (%d) in element %s <-> ", srcpad->name, srcpad->type, gst_element_get_name(src)); - g_print("pad \"%s\" (%d) in element %s\n", sinkpad->name, sinkpad->type, gst_element_get_name(sink)); + g_print("gstpipeline: autoconnect pad \"%s\" (%d) in element %s <-> ", + srcpad->name, srcpad->type, gst_element_get_name(src)); + g_print("pad \"%s\" (%d) in element %s\n", sinkpad->name, + sinkpad->type, gst_element_get_name(sink)); connected = TRUE; goto end; } @@ -223,6 +242,51 @@ end: } /** + * gst_pipeline_add_src: + * @pipeline: the pipeline to add the src to + * @src: the src to add to the pipeline + * + * Adds a src element to the pipeline. This element + * will be used as a src for autoplugging. If you add more + * than one src element, the previously added element will + * be removed. + */ +void gst_pipeline_add_src(GstPipeline *pipeline, GstElement *src) +{ + g_return_if_fail(pipeline != NULL); + g_return_if_fail(GST_IS_PIPELINE(pipeline)); + g_return_if_fail(src != NULL); + g_return_if_fail(GST_IS_ELEMENT(src)); + + if (pipeline->src) { + printf("gstpipeline: *WARNING* removing previously added element \"%s\"\n", + gst_element_get_name(pipeline->src)); + gst_bin_remove(GST_BIN(pipeline), pipeline->src); + } + pipeline->src = src; + gst_bin_add(GST_BIN(pipeline), src); +} + +/** + * gst_pipeline_add_sink: + * @pipeline: the pipeline to add the sink to + * @sink: the sink to add to the pipeline + * + * Adds a sink element to the pipeline. This element + * will be used as a sink for autoplugging + */ +void gst_pipeline_add_sink(GstPipeline *pipeline, GstElement *sink) +{ + g_return_if_fail(pipeline != NULL); + g_return_if_fail(GST_IS_PIPELINE(pipeline)); + g_return_if_fail(sink != NULL); + g_return_if_fail(GST_IS_ELEMENT(sink)); + + pipeline->sinks = g_list_prepend(pipeline->sinks, sink); + gst_bin_add(GST_BIN(pipeline), sink); +} + +/** * gst_pipeline_autoplug: * @pipeline: the pipeline to autoplug * @@ -240,70 +304,70 @@ gboolean gst_pipeline_autoplug(GstPipeline *pipeline) { guint16 src_type = 0, sink_type = 0; gboolean complete = FALSE; + g_return_val_if_fail(pipeline != NULL, FALSE); g_return_val_if_fail(GST_IS_PIPELINE(pipeline), FALSE); - g_print("GstPipeline: autopluging pipeline \"%s\"\n", gst_element_get_name(GST_ELEMENT(pipeline))); + g_print("GstPipeline: autopluging pipeline \"%s\"\n", + gst_element_get_name(GST_ELEMENT(pipeline))); + + + // fase 1, run typedetect on the source if needed... + if (!pipeline->src) { + g_print("GstPipeline: no source detected, can't autoplug pipeline \"%s\"\n", + gst_element_get_name(GST_ELEMENT(pipeline))); + return FALSE; + } - elements = gst_bin_get_list(GST_BIN(pipeline)); + factory = gst_element_get_factory(pipeline->src); - // fase 1, find all the sinks and sources... FIXME need better way to do this... + src_types = factory->src_types; + if (src_types == NULL) { + g_print("GstPipeline: source \"%s\" has no MIME type, running typefind...\n", + gst_element_get_name(pipeline->src)); + + src_type = gst_pipeline_typefind(pipeline, pipeline->src); + + if (src_type) { + g_print("GstPipeline: source \"%s\" type found %d\n", gst_element_get_name(pipeline->src), + src_type); + } + else { + g_print("GstPipeline: source \"%s\" has no type\n", gst_element_get_name(pipeline->src)); + return FALSE; + } + } + else { + while (src_types) { + // FIXME loop over types and find paths... + src_types = g_list_next(src_types); + } + } + + srcelement = pipeline->src; + + elements = pipeline->sinks; + + // fase 2, find all the sinks.. while (elements) { element = GST_ELEMENT(elements->data); if (GST_IS_SINK(element)) { g_print("GstPipeline: found sink \"%s\"\n", gst_element_get_name(element)); - if (sink_type) { - g_print("GstPipeline: multiple sinks detected, can't autoplug pipeline \"%s\"\n", gst_element_get_name(GST_ELEMENT(pipeline))); - return FALSE; - } sinkelement = element; factory = gst_element_get_factory(element); sink_types = factory->sink_types; if (sink_types == NULL) { - g_print("GstPipeline: sink \"%s\" has no MIME type, can't autoplug \n", gst_element_get_name(element)); + g_print("GstPipeline: sink \"%s\" has no MIME type, can't autoplug \n", + gst_element_get_name(element)); return FALSE; } else { sink_type = GPOINTER_TO_UINT(sink_types->data); - g_print("GstPipeline: sink \"%s\" has MIME type %d \n", gst_element_get_name(element), sink_type); - } - } - else if (GST_IS_SRC(element)) { - g_print("GstPipeline: found source \"%s\"\n", gst_element_get_name(element)); - - if (src_type) { - g_print("GstPipeline: multiple sources detected, can't autoplug pipeline \"%s\"\n", gst_element_get_name(GST_ELEMENT(pipeline))); - return FALSE; + g_print("GstPipeline: sink \"%s\" has MIME type %d \n", + gst_element_get_name(element), sink_type); } - - srcelement = element; - - factory = gst_element_get_factory(element); - - src_types = factory->src_types; - if (src_types == NULL) { - g_print("GstPipeline: source \"%s\" has no MIME type, running typefind...\n", gst_element_get_name(element)); - - src_type = gst_pipeline_typefind(pipeline, element); - - if (src_type) { - g_print("GstPipeline: source \"%s\" type found %d\n", gst_element_get_name(element), src_type); - } - else { - g_print("GstPipeline: source \"%s\" has no type\n", gst_element_get_name(element)); - return FALSE; - } - } - else { - while (src_types) { - src_types = g_list_next(src_types); - } - } - } - else { - g_print("GstPipeline: found invalid element \"%s\", not source or sink\n", gst_element_get_name(element)); } elements = g_list_next(elements); @@ -312,7 +376,7 @@ gboolean gst_pipeline_autoplug(GstPipeline *pipeline) { factories = gst_type_get_sink_to_src(src_type, sink_type); while (factories) { - // fase 2: find elements to form a pad + // fase 3: find elements to form a pad factory = (GstElementFactory *)(factories->data); @@ -335,7 +399,8 @@ gboolean gst_pipeline_autoplug(GstPipeline *pipeline) { return TRUE; } - g_print("GstPipeline: unable to autoplug pipeline \"%s\"\n", gst_element_get_name(GST_ELEMENT(pipeline))); + g_print("GstPipeline: unable to autoplug pipeline \"%s\"\n", + gst_element_get_name(GST_ELEMENT(pipeline))); return FALSE; } diff --git a/gst/gstpipeline.h b/gst/gstpipeline.h index f186eaf..7416ff6 100644 --- a/gst/gstpipeline.h +++ b/gst/gstpipeline.h @@ -48,6 +48,9 @@ typedef struct _GstPipelineClass GstPipelineClass; struct _GstPipeline { GstBin bin; + + GstElement *src; // we only allow one src element + GList *sinks; // and multiple sinks }; struct _GstPipelineClass { @@ -60,6 +63,9 @@ GstElement *gst_pipeline_new(guchar *name); gboolean gst_pipeline_autoplug(GstPipeline *pipeline); +void gst_pipeline_add_src(GstPipeline *pipeline, GstElement *src); +void gst_pipeline_add_sink(GstPipeline *pipeline, GstElement *sink); + void gst_pipeline_iterate(GstPipeline *pipeline); #ifdef __cplusplus diff --git a/libs/getbits/gstgetbits.c b/libs/getbits/gstgetbits.c index 53640c9..a953651 100644 --- a/libs/getbits/gstgetbits.c +++ b/libs/getbits/gstgetbits.c @@ -184,7 +184,7 @@ void gst_getbits_init(gst_getbits_t *gb, GstGetbitsCallback callback, void *data gb->showbits = _gst_showbits_i386; gb->flushbits = _gst_flushbits_i386; gb->backbits = _gst_getbits_back_i386; - printf("gstgetbits: using intel optimized versions\n"); + printf("gstgetbits: using i386 optimized versions\n"); #else gb->get1bit = _gst_get1bit_int; gb->getbits = _gst_getbits_int; diff --git a/plugins/elements/gstdisksrc.c b/plugins/elements/gstdisksrc.c index ea77836..d12ad9b 100644 --- a/plugins/elements/gstdisksrc.c +++ b/plugins/elements/gstdisksrc.c @@ -221,7 +221,6 @@ void gst_disksrc_push(GstSrc *src) { else if (readbytes == 0) { gst_src_signal_eos(GST_SRC(disksrc)); gst_buffer_unref(buf); - GST_STATE(src) = GST_STATE_PAUSED; return; } diff --git a/tests/old/examples/helloworld2/helloworld2.c b/tests/old/examples/helloworld2/helloworld2.c index 2405310..f687ef6 100644 --- a/tests/old/examples/helloworld2/helloworld2.c +++ b/tests/old/examples/helloworld2/helloworld2.c @@ -38,8 +38,8 @@ int main(int argc,char *argv[]) g_assert(audiosink != NULL); /* add objects to the main pipeline */ - gst_bin_add(GST_BIN(pipeline), disksrc); - gst_bin_add(GST_BIN(pipeline), audiosink); + gst_pipeline_add_src(GST_PIPELINE(pipeline), disksrc); + gst_pipeline_add_sink(GST_PIPELINE(pipeline), audiosink); if (!gst_pipeline_autoplug(GST_PIPELINE(pipeline))) { g_print("unable to handle stream\n"); diff --git a/tests/old/examples/thread/thread.c b/tests/old/examples/thread/thread.c index 1635219..4d8073d 100644 --- a/tests/old/examples/thread/thread.c +++ b/tests/old/examples/thread/thread.c @@ -45,8 +45,8 @@ int main(int argc,char *argv[]) g_assert(audiosink != NULL); /* add objects to the main pipeline */ - gst_bin_add(GST_BIN(pipeline), disksrc); - gst_bin_add(GST_BIN(pipeline), audiosink); + gst_pipeline_add_src(GST_PIPELINE(pipeline), disksrc); + gst_pipeline_add_sink(GST_PIPELINE(pipeline), audiosink); if (!gst_pipeline_autoplug(GST_PIPELINE(pipeline))) { g_print("unable to handle stream\n");