diff --git a/docs/manual/dynamic.sgml b/docs/manual/dynamic.sgml index b7b3fdc6cd..209d08a856 100644 --- a/docs/manual/dynamic.sgml +++ b/docs/manual/dynamic.sgml @@ -1,6 +1,16 @@ Dynamic pipelines + this chapter we will see how you can create a dynamic pipleine. A dynamic + pipeline is a pipeline that is updated or created while media is flowing + through it. We will create a partial pipeline first and add more elements + while the pipeline is playing. Dynamic pipelines cause all sorts of + scheduling issues and will remain a topic of research for a long time in + GStreamer. + + + We will show how to create an mpeg1 video player using the dynamic pipeline + diff --git a/test/mp2tomp1.c b/test/mp2tomp1.c index 78ce6057b2..768cfd7693 100644 --- a/test/mp2tomp1.c +++ b/test/mp2tomp1.c @@ -6,20 +6,43 @@ #include #include -GstElement *mux; -GstElement *merge_subtitles; +static GstElement *mux = NULL; +static GstElement *merge_subtitles; +static GstElement *fdsink; -void eof(GstElement *src) { +static void +eof(GstElement *src) +{ g_print("have eos, quitting\n"); exit(0); } -void mp2tomp1(GstElement *parser,GstPad *pad, GstElement *pipeline) { +static GstPad* +create_muxer (GstElement *pipeline, gchar *type, gchar *number) +{ + if (!mux) { + mux = gst_elementfactory_make("system_encode","mux"); + g_return_val_if_fail(mux != NULL, NULL); + + gst_bin_add(GST_BIN(pipeline),GST_ELEMENT(mux)); + gst_bin_add(GST_BIN(pipeline),GST_ELEMENT(fdsink)); + gst_pad_connect(gst_element_get_pad(mux,"src"), + gst_element_get_pad(fdsink,"sink")); + } + gtk_object_set(GTK_OBJECT(mux), type, number,NULL); + + return gst_element_get_pad(mux,g_strconcat (type, "_", number, NULL)); +} + +static void +mp2tomp1 (GstElement *parser, GstPad *pad, GstElement *pipeline) +{ GstElement *parse_audio, *parse_video, *decode, *decode_video, *play, *encode, *audio_resample; GstElement *smooth, *median; GstElement *audio_queue, *video_queue; GstElement *audio_thread, *video_thread; GstElement *videoscale, *audio_encode; + GstPad *muxerpad; g_print("***** a new pad %s was created\n", gst_pad_get_name(pad)); gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_PAUSED); @@ -27,10 +50,6 @@ void mp2tomp1(GstElement *parser,GstPad *pad, GstElement *pipeline) { // connect to audio pad //if (0) { if (strncmp(gst_pad_get_name(pad), "private_stream_1.0", 18) == 0) { - gst_plugin_load("ac3parse"); - gst_plugin_load("ac3dec"); - gst_plugin_load("audioscale"); - gst_plugin_load("mpegaudio"); // construct internal pipeline elements parse_audio = gst_elementfactory_make("ac3parse","parse_audio"); g_return_if_fail(parse_audio != NULL); @@ -54,7 +73,7 @@ void mp2tomp1(GstElement *parser,GstPad *pad, GstElement *pipeline) { gst_bin_add(GST_BIN(audio_thread),GST_ELEMENT(audio_resample)); gst_bin_add(GST_BIN(audio_thread),GST_ELEMENT(audio_encode)); - gtk_object_set(GTK_OBJECT(mux),"audio","00",NULL); + muxerpad = create_muxer (pipeline, "audio", "00"); // set up pad connections gst_element_add_ghost_pad(GST_ELEMENT(audio_thread), @@ -66,7 +85,7 @@ void mp2tomp1(GstElement *parser,GstPad *pad, GstElement *pipeline) { gst_pad_connect(gst_element_get_pad(audio_resample,"src"), gst_element_get_pad(audio_encode,"sink")); gst_pad_connect(gst_element_get_pad(audio_encode,"src"), - gst_element_get_pad(mux,"audio_00")); + muxerpad); // construct queue and connect everything in the main pipelie audio_queue = gst_elementfactory_make("queue","audio_queue"); @@ -83,11 +102,9 @@ void mp2tomp1(GstElement *parser,GstPad *pad, GstElement *pipeline) { g_print("setting to READY state\n"); gst_element_set_state(GST_ELEMENT(audio_thread),GST_STATE_READY); } else if (strncmp(gst_pad_get_name(pad), "subtitle_stream_4", 17) == 0) { - gst_pad_connect(pad, - gst_element_get_pad(merge_subtitles,"subtitle")); + //gst_pad_connect(pad, + // gst_element_get_pad(merge_subtitles,"subtitle")); } else if (strncmp(gst_pad_get_name(pad), "audio_", 6) == 0) { - gst_plugin_load("mp3parse"); - gst_plugin_load("mpg123"); // construct internal pipeline elements parse_audio = gst_elementfactory_make("mp3parse","parse_audio"); g_return_if_fail(parse_audio != NULL); @@ -129,21 +146,14 @@ void mp2tomp1(GstElement *parser,GstPad *pad, GstElement *pipeline) { } else if (strncmp(gst_pad_get_name(pad), "video_", 6) == 0) { //} else if (0) { - gst_plugin_load("mp1videoparse"); - gst_plugin_load("mpeg2play"); - gst_plugin_load("mpeg2subt"); - gst_plugin_load("smooth"); - gst_plugin_load("median"); - gst_plugin_load("videoscale"); - gst_plugin_load("mpeg2enc"); //gst_plugin_load("mpeg1encoder"); // construct internal pipeline elements - parse_video = gst_elementfactory_make("mp1videoparse","parse_video"); + parse_video = gst_elementfactory_make("mp2videoparse","parse_video"); g_return_if_fail(parse_video != NULL); decode_video = gst_elementfactory_make("mpeg2play","decode_video"); g_return_if_fail(decode_video != NULL); - merge_subtitles = gst_elementfactory_make("mpeg2subt","merge_subtitles"); - g_return_if_fail(merge_subtitles != NULL); + //merge_subtitles = gst_elementfactory_make("mpeg2subt","merge_subtitles"); + //g_return_if_fail(merge_subtitles != NULL); videoscale = gst_elementfactory_make("videoscale","videoscale"); g_return_if_fail(videoscale != NULL); gtk_object_set(GTK_OBJECT(videoscale),"width",352, "height", 288,NULL); @@ -158,12 +168,12 @@ void mp2tomp1(GstElement *parser,GstPad *pad, GstElement *pipeline) { gtk_object_set(GTK_OBJECT(smooth),"active",FALSE,NULL); encode = gst_elementfactory_make("mpeg2enc","encode"); g_return_if_fail(encode != NULL); - //gtk_object_set(GTK_OBJECT(encode),"frames_per_second",25.0,NULL); - gtk_object_set(GTK_OBJECT(encode),"frames_per_second",29.97,NULL); + gtk_object_set(GTK_OBJECT(encode),"frames_per_second",25.0,NULL); + //gtk_object_set(GTK_OBJECT(encode),"frames_per_second",29.97,NULL); //encode = gst_elementfactory_make("mpeg1encoder","encode"); //gtk_object_set(GTK_OBJECT(show),"width",640, "height", 480,NULL); - gtk_object_set(GTK_OBJECT(mux),"video","00",NULL); + muxerpad = create_muxer (pipeline, "video", "00"); // create the thread and pack stuff into it video_thread = gst_thread_new("video_thread"); @@ -185,15 +195,15 @@ void mp2tomp1(GstElement *parser,GstPad *pad, GstElement *pipeline) { gst_pad_connect(gst_element_get_pad(decode_video,"src"), gst_element_get_pad(median,"sink")); gst_pad_connect(gst_element_get_pad(median,"src"), - gst_element_get_pad(merge_subtitles,"video")); - gst_pad_connect(gst_element_get_pad(merge_subtitles,"src"), + // gst_element_get_pad(merge_subtitles,"video")); + //gst_pad_connect(gst_element_get_pad(merge_subtitles,"src"), gst_element_get_pad(videoscale,"sink")); gst_pad_connect(gst_element_get_pad(videoscale,"src"), gst_element_get_pad(smooth,"sink")); gst_pad_connect(gst_element_get_pad(smooth,"src"), gst_element_get_pad(encode,"sink")); gst_pad_connect(gst_element_get_pad(encode,"src"), - gst_element_get_pad(mux,"video_00")); + muxerpad); // construct queue and connect everything in the main pipeline video_queue = gst_elementfactory_make("queue","video_queue"); @@ -216,15 +226,12 @@ void mp2tomp1(GstElement *parser,GstPad *pad, GstElement *pipeline) { int main(int argc,char *argv[]) { GstElement *pipeline, *src, *parse; - GstElement *fdsink; GstElementFactory *fdsinkfactory; int fd; g_print("have %d args\n",argc); gst_init(&argc,&argv); - gst_plugin_load("mpeg2parse"); - gst_plugin_load("system_encode"); pipeline = gst_pipeline_new("pipeline"); g_return_val_if_fail(pipeline != NULL, -1); @@ -244,8 +251,6 @@ int main(int argc,char *argv[]) { parse = gst_elementfactory_make("mpeg2parse","parse"); g_return_val_if_fail(parse != NULL, -1); - mux = gst_elementfactory_make("system_encode","mux"); - g_return_val_if_fail(mux != NULL, -1); fd = open(argv[2],O_CREAT|O_RDWR|O_TRUNC, S_IREAD|S_IWRITE); g_return_val_if_fail(fd >= 0, -1); fdsinkfactory = gst_elementfactory_find("fdsink"); @@ -256,8 +261,7 @@ int main(int argc,char *argv[]) { gst_bin_add(GST_BIN(pipeline),GST_ELEMENT(src)); gst_bin_add(GST_BIN(pipeline),GST_ELEMENT(parse)); - gst_bin_add(GST_BIN(pipeline),GST_ELEMENT(mux)); - gst_bin_add(GST_BIN(pipeline),GST_ELEMENT(fdsink)); + gtk_signal_connect(GTK_OBJECT(parse),"new_pad",mp2tomp1, pipeline); @@ -265,8 +269,6 @@ int main(int argc,char *argv[]) { gst_pad_connect(gst_element_get_pad(src,"src"), gst_element_get_pad(parse,"sink")); - gst_pad_connect(gst_element_get_pad(mux,"src"), - gst_element_get_pad(fdsink,"sink")); g_print("setting to READY state\n"); gst_element_set_state(GST_ELEMENT(pipeline),GST_STATE_PLAYING);