tee: Check for the removed pad flag also in the slow pushing path
[platform/upstream/gstreamer.git] / docs / random / autoplug2
1
2 1) The Autoplugger API
3 ----------------------
4
5 We'll first describe how to use the autoplugger. We will provide
6 a use case: autoplug an mpeg1 system stream for audio/video playback.
7
8
9 a) creating an autoplugger
10 --------------------------
11
12 Before any autoplugging can be done, you'll have to create an 
13 autoplugger object. Autoplugger objects (autopluggers) are 
14 provided by plugins and are created with gst_autoplugfactor_make().
15
16 GStreamer has provisions for two types of autopluggers:
17
18  - regular autopluggers, which act as a complex element construction
19    mechanism. They usually don't create threads and operate solely on
20    GstCaps* for the source and destination. The complex elements 
21    created by regular autopluggers have src and sink pad compatible 
22    with the requested GstCaps*.
23  
24  - renderer autopluggers, which are designed to create a complex
25    object that can be used to playback media. Renderer autoplugged
26    complex elements have no src pads, only one sink pad.
27
28 We'll create a renderer autoplugger like this:
29
30 !
31 !  GstAutoplug *autoplug;
32 !
33 !  autoplug = gst_autoplugfactory_make ("staticrender");
34 !
35
36
37 b) finding out the source media type.
38 -------------------------------------
39
40 Before we can start the autoplugger, we have to find out the 
41 source media type. This can be done using the typefind functions 
42 provided by various plugins.
43
44 We will create a little pipeline to detect the media type by connecting
45 a disksrc element to a typefind element. The typefind element will 
46 repeatedly call all registered typefind functions with the buffer it
47 receives on its sink pad. when a typefind function returns a non NULL
48 GstCaps*, that caps is set to the sink pad of the typefind element and
49 a signal is emitted to notify the app.
50
51 Due to caps negotiation, the disksrc will have the detected GstCaps* 
52 set on its src pad.
53
54 We typically use a function like below to detect the type of a media stream
55 on an element (typically a disksrc). The function accepts a pipeline and the
56 element inside the pipeline on which the typefind should be performed (passing
57 a GstPad* is probably a better option FIXME).
58
59
60 ! static GstCaps*
61 ! gst_play_typefind (GstBin *bin, GstElement *element)
62 ! {
63 !   GstElement *typefind;
64 !   GstCaps *caps = NULL;
65
66 !   typefind = gst_elementfactory_make ("typefind", "typefind");
67 !   g_return_val_if_fail (typefind != NULL, FALSE);
68
69 !   gst_pad_connect (gst_element_get_pad (element, "src"),
70 !                    gst_element_get_pad (typefind, "sink"));
71
72 !   gst_bin_add (bin, typefind);
73
74 !   gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PLAYING);
75
76 !   // push a buffer... the have_type signal handler will set the found flag
77 !   gst_bin_iterate (bin);
78
79 !   gst_element_set_state (GST_ELEMENT (bin), GST_STATE_NULL);
80
81 !   caps = gst_pad_get_caps (gst_element_get_pad (element, "src"));
82
83 !   gst_pad_disconnect (gst_element_get_pad (element, "src"),
84 !                       gst_element_get_pad (typefind, "sink"));
85 !   gst_bin_remove (bin, typefind);
86 !   gst_object_unref (GST_OBJECT (typefind));
87
88 !   return caps;
89 ! }
90
91
92 Also note that the disksrc was added to the pipeline before calling this
93 typefind function.
94
95 When the function returns a non-NULL pointer, the media type has been 
96 determined and autoplugging can commence.
97
98 Assume that in our mpeg1 use case the above function returns a GstCaps* 
99 like:
100
101 !
102 !  srccaps = GST_CAPS_NEW ("mpeg1system_typefind",
103 !                          "video/mpeg",
104 !                            "mpegversion",  GST_PROPS_INT (1),
105 !                            "systemstream", GST_PROPS_BOOLEAN (TRUE)
106 !                         );
107 !
108
109
110 c) Performing the autoplugging
111 ------------------------------
112
113 Since we use the renderer API, we have to create the output elements
114 that are going to be used as the final sink elements.
115
116 !
117 !  osssink = gst_elementfactory_make("osssink", "play_audio");
118 !  videosink = gst_elementfactory_make("xvideosink", "play_video");
119 !  
120   
121 We then create a complex element using the following code.
122
123 !
124 !  new_element = gst_autoplug_to_renderers (autoplug,
125 !           srccaps,
126 !           videosink,
127 !           osssink,
128 !           NULL);
129 !
130 !  if (!new_element) {
131 !    g_print ("could not autoplug, no suitable codecs found...\n");
132 !    exit (-1);
133 !  }
134 !
135
136 2) Autoplugging internals
137 -------------------------
138
139 We will now describe the internals of the above gst_autoplug_to_renderers()
140 function call. This code is implemented in a plugin found in:
141
142     gst/autoplug/gststaticautoplugrender.c
143
144
145
146 a) phase1: create lists of factories.
147 ---------------------------------------
148
149 The autoplugger will start with executing the following piece of
150 code:
151
152 !
153 ! i = 0;
154 !
155 ! for each sink:
156 ! {
157 !   sinkpad = take the first sinkpad of the sink (HACK)
158 !   
159 !   list[i] = gst_autoplug_caps (srccaps, sinkpad->caps);
160 !     
161 !   i++;
162 ! }
163 !
164
165 gst_autoplug_caps will figure out (based on the padtemplates)
166 which elementfactories are needed to connect srccaps to sinkpad->caps
167 and will return them in a list.
168
169 The element list is created by using a modified shortest path algorithm
170 by Dijkstra (http://www.orie.cornell.edu/~or115/handouts/handout3/handout3.html).
171 The nodes of the graph are the elementfactories and the weight of the
172 arcs is based on the pad compatibility of the padtemplates of the 
173 elementfactory. For incompatible elementfactories, we use a weight of 
174 MAX_COST (999999) and for compatible padtemplates we use 1.
175
176 ex. we have two sinks with following caps:
177
178 !
179 !       video/raw                   audio/raw
180 !       "...."                       "...."
181 !
182
183 gst_autoplug_caps will figure out that for the first sink the following
184 elements are needed:
185
186 !
187 !   mpeg1parse, mp1videoparse, mpeg_play
188 !
189
190 for the second sink the following is needed:
191  
192 !
193 !   mpeg1parse, mad
194 !
195
196 Note that for the audio connection the element list "mpeg1parse, mp3parse,
197 mpg123" would also connect the srccaps to the audiosink caps. Since the
198 "mpeg1parse, mad" list is shorter, it it always preferred by the autoplugger.
199
200 We now have two lists of elementfactories.
201
202
203 b) phase2: collect common elements from the lists and add them to a bin.
204 ------------------------------------------------------------------------
205
206 The rationale is that from the lists we have created in phase1, there
207 must be some element that is a splitter and that it has to come first (HACK)
208 We try to find that element by comparing the lists until an element differs.
209
210 We start by creating a toplevel bin that is going to be our complex element.
211
212 In our use-case we find that mpeg1parse is an element common to both lists,
213 so we add it to the bin. We then try to find a good ghostpad for the resulting
214 complex element. This is done by looping over the sink pads of the first common
215 element and taking the pad that is compatible with the srcaps.
216
217 We end up with a bin like this:
218 !
219 !  (----------------------)
220 !  ! autoplug_bin         !
221 !  !                      !
222 !  !       (------------) !
223 !  !       ! mpeg1parse ! !
224 !  !   - sink           ! !
225 !  !  /    (------------) !
226 ! sink                    !
227 !  (----------------------)
228 !
229
230
231 c) phase3: add remaining elements
232 ---------------------------------
233
234 now we loop over all the list and try to add the remaining elements
235
236 (HACK) we always use a new thread for the elements when there is a common
237 element found.
238
239 if a new thread is needed (either because the previous element is a common
240 element or the object flag of the next element is set to GST_SUGGEST_THREAD)
241 we add a queue to the bin and we add a new thread. We add the elements to
242 the bin and connect them using gst_pipeline_pads_autoplug. 
243
244 we finally arrive at the sink element and we're done.
245
246 ex.
247     
248      we have just found our mpeg1parse common element, so we start a thread.
249      We add a queue to the bin and a new thread, we add the elements
250      mp1videoparse and mpeg_play to the thread. We arrive at the videosink, we
251      see that the SUGGEST_THREAD flag is set, we add a queue and a thread and
252      add the videosink in the thread.
253  
254      the same procedure happens for the audio part. We are now left with the
255      following pipeline:
256
257      We will also have set a signal "new_pad" on the mpeg1parse element because
258      the element mp1videoparse could not be connected to the element just yet.
259
260   (---------------------------------------------------------------------------------------------)
261   !autoplug_bin                                                                                 !
262   !                                                                                             !
263   !                                   (----------------------------------------) (------------) !
264   !                                   !thread                                  ! ! thread     ! !
265   !                         (-----)   ! (-------------)   (---------)  (-----) ! ! (---------)! !
266   !                         !queue!   ! !mp1videoparse!   !mpeg_play!  !queue! ! ! !videosink!! !
267   !                         sink src-sink            src-sink      src-sink src-sink         !! !
268   !       (-----------)     (-----)   ! (-------------)   (---------)  (-----) ! ! (---------)! !
269   !       ! mpeg1parse!               (----------------------------------------) (------------) !
270   !   - sink          !                                                                         !
271   !  /    (-----------)                                                                         !
272  sink                                 (----------------------------------------) (------------) !
273   !                                   !thread                                  ! ! thread     ! !
274   !                         (-----)   ! (-------------)                (-----) ! ! (---------)! !
275   !                         !queue!   ! !mad          !                !queue! ! ! !videosink!! !
276   !                         sink src-sink            src ------------ sink  src-sink         !! !
277   !                         (-----)   ! (-------------)                (-----) ! ! (---------)! !
278   !                                   (----------------------------------------) (------------) !
279   (---------------------------------------------------------------------------------------------)
280
281    The autoplugger will return the autoplug_bin. the app will then connect the 
282    disksrc to the sinkpad of the autoplugged bin.
283
284    Then we play, create_plan happens, data is flowing and the "new_pad" signal is called
285    from mpeg1parse, gst_pipeline_pad_autoplug is called and the connection between
286    mpeg1parse and the videoqueue is made. same for audio.
287
288    Et voila. same procedure for mp3/vorbis/avi/qt/mpeg2 etc...
289