COMPLETELY OUTDATED ------------------- A little explanation of the first autoplugger in GStreamer: Autoplugging is implemented in the following places: gstpipeline.c : construction of the pipeline gstautoplug.c : selection of the elementfactories needed for autoplugging 1) pipeline setup ----------------- before any autoplugging will take place, a new GstPipeline has to be created. The autoplugger needs to have a src element and one or more sink elements. the autoplugger will try to find the elements needed to connect the src element to the sinks. using: gst_pipeline_add_src (GstPipeline *pipeline, GstElement *element); a source element is added to the pipeline. only one src element can be added for now. using: gst_pipeline_add_sink (GstPipeline *pipeline, GstElement *element); a sink element can be added to the pipeline. 2) starting autoplug -------------------- when the pipeline has been set up as above, you will call gst_pipeline_autoplug (GstPipeline *pipeline); to start the autoplugger. this will be done in four phases ex. we are going to autoplug an mpeg1 system stream. 2a) phase1: figure out the type (GstCaps) of the src element. ------------------------------------------------------------- the gsttypefind element is connected to the "src" pad of the source element. gst_bin_iterate is called in a loop until gsttypefind signals "have_type". the gst_bin_iterate is stopped and the GstCaps is retrieved from the gsttypefind element. gsttypefind is disconnected from the src element and removed from the bin. the GstCaps of the source element is called src_caps later on. ex. all typefind functions are tried and the one in mpeg1types will return a GstCaps: video/mpeg, "systemstream", GST_PROPS_BOOLEAN (TRUE), "mpegversion", GST_PROPS_INT (1), NULL 2b) phase2: create lists of factories. --------------------------------------- for each sink: { sinkpad = take the first sinkpad of the sink (HACK) call list[i] = gst_autoplug_caps (src_caps, sinkpad->caps); I++; } gst_autoplug_caps will figure out (based on the padtemplates) which elementfactories are needed to connect src_caps to sinkpad->caps and will return them in a list. ex. we have two sinks with following caps: video/raw audio/raw "...." "...." gst_autoplug_caps will figure out that for the first sink the following elements are needed: mpeg1parse, mp1videoparse, mpeg_play for the second sink the following is needed: mpeg1parse, mp3parse, mpg123 We now have two lists of elementfactories. 2c) phase3: collect common elements from the lists. --------------------------------------------------- the rationale is that from the lists we have created in phase2, there must be some element that is a splitter and that it has to come first (HACK) We try to find that element by comparing the lists until an element differs. we add the common elements to the bin and run gst_pipeline_pads_autoplug. this function will loop over the pads of the previous element and the one we just added, and tries to connect src to sink if possible. If a connection between the two elements could not be made, a signal "new_pad" is connected to the element so that pad connection can occur later on when the pad is actually created. ex. when we compare the two lists we see that we have common element: mpeg1parse. we add this element to the bin and try to connect it to the previous element in the bin, the disksrc. we see that the src pad of the disksrc and the sinkpad of the mpeg1parse element can be connected because they are compatible. We have a pipeline like: ---------) (-------- disksrc ! ! mpeg1parse src --- sink ---------) (-------- 2d) phase4: add remaining elements ---------------------------------- now we loop over all the list and try to add the remaining elements (HACK) we always use a new thread for the elements when there is a common element found. if a new thread is needed (either bacuase the previous element is a common element or the object flag of the next element is set to GST_SUGGEST_THREAD) we add a queue to the bin and we add a new thread. We add the elements to the bin and connect them using gst_pipeline_pads_autoplug. If we add a queue, we have to copy the caps of the sink element of the queue to the src pad of the queue (else they won't connect) we finally arrive at the sink element and we're done. ex. we have just found our mpeg1parse common element, so we start a thread. We add a queue to the bin and a new thread, we add the elements mp1videoparse and mpeg_play to the thread. We arrive at the videosink, we see that the SUGGEST_THREAD flag is set, we add a queue and a thread and add the videosink in the thread. the same procedure happens for the audio part. We are now left with the following pipeline: We will also have set a signal "new_pad" on the mpeg1parse element because the element mp1videoparse could not be connected to the element just yet. (------------------------------------) (---------- !thread ! ! thread ! (-------------) (---------) ! ! (---------) ! !mp1videoparse! !mpeg_play! ! ! !videosink! videoqueue--sink src -- sink src -- queue --- sink ! ---------) (-----------) ! (-------------) (---------) ! ! (---------) disksrc ! ! mpeg1parse! (------------------------------------) (------------- src --- sink ! ---------) (-----------) queue----- same for audio then we play, create_plan happens, data is flowing and the "new_pad" signal is called from mpeg1parse, gst_pipeline_pad_autoplug is called and the connection between mpeg1parse and the videoqueue is made. same for audio. voila. smame procedure for mp3/vorbis/avi/qt/mpeg2 etc... Problems: --------- this is obviously a very naive solution. the creation of the elements actually happens beforehand. MPEG2, for one, fails because there are multiple possibilities to go from the mpeg demuxer to audio/raw (ac3, mp3) Also any intermedia elements like mixers (subtitles) are not possible because we assume that after the common elements, the streams to not converge anymore.