1 <chapter id="chapter-advanced-request">
2 <title>Request and Sometimes pads</title>
4 Until now, we've only dealt with pads that are always available. However,
5 there's also pads that are only being created in some cases, or only if
6 the application requests the pad. The first is called a
7 <emphasis>sometimes</emphasis>; the second is called a
8 <emphasis>request</emphasis> pad. The availability of a pad (always,
9 sometimes or request) can be seen in a pad's template. This chapted will
10 discuss when each of the two is useful, how they are created and when
11 they should be disposed.
14 <sect1 id="section-reqpad-sometimes" xreflabel="Sometimes pads">
15 <title>Sometimes pads</title>
17 A <quote>sometimes</quote> pad is a pad that is created under certain
18 conditions, but not in all cases. This mostly depends on stream content:
19 demuxers will generally parse the stream header, decide what elementary
20 (video, audio, subtitle, etc.) streams are embedded inside the system
21 stream, and will then create a sometimes pad for each of those elementary
22 streams. At its own choice, it can also create more than one instance of
23 each of those per element instance. The only limitation is that each
24 newly created pad should have a unique name. Sometimes pads are disposed
25 when the stream data is disposed, too (i.e. when going from PAUSED to the
26 READY state). You should <emphasis>not</emphasis> dispose the pad on EOS,
27 because someone might re-activate the pipeline and seek back to before
28 the end-of-stream point. The stream should still stay valid after EOS, at
29 least until the stream data is disposed. In any case, the element is
30 always the owner of such a pad.
33 The example code below will parse a text file, where the first line is
34 a number (n). The next lines all start with a number (0 to n-1), which
35 is the number of the source pad over which the data should be sent.
45 The code to parse this file and create the dynamic <quote>sometimes</quote>
46 pads, looks like this:
49 typedef struct _GstMyFilter {
56 gst_my_filter_base_init (GstMyFilterClass *klass)
58 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
59 static GstStaticPadTemplate src_factory =
60 GST_STATIC_PAD_TEMPLATE (
64 GST_STATIC_CAPS ("ANY")
67 gst_element_class_add_pad_template (element_class,
68 gst_static_pad_template_get (&src_factory));
73 gst_my_filter_init (GstMyFilter *filter)
76 filter->firstrun = TRUE;
77 filter->srcpadlist = NULL;
81 * Get one line of data - without newline.
85 gst_my_filter_getline (GstMyFilter *filter)
90 /* max. line length is 512 characters - for safety */
91 for (n = 0; n < 512; n++) {
92 num = gst_bytestream_peek_bytes (filter->bs, &data, n + 1);
97 if (data[n] == '\n') {
98 GstBuffer *buf = gst_buffer_new_and_alloc (n + 1);
100 gst_bytestream_peek_bytes (filter->bs, &data, n);
101 memcpy (GST_BUFFER_DATA (buf), data, n);
102 GST_BUFFER_DATA (buf)[n] = '\0';
103 gst_bytestream_flush_fast (filter->bs, n + 1);
111 gst_my_filter_loopfunc (GstElement *element)
113 GstMyFilter *filter = GST_MY_FILTER (element);
119 if (filter->firstrun) {
120 GstElementClass *klass;
121 GstPadTemplate *templ;
124 if (!(buf = gst_my_filter_getline (filter))) {
125 gst_element_error (element, STREAM, READ, (NULL),
126 ("Stream contains no header"));
129 num = atoi (GST_BUFFER_DATA (buf));
130 gst_buffer_unref (buf);
132 /* for each of the streams, create a pad */
133 klass = GST_ELEMENT_GET_CLASS (filter);
134 templ = gst_element_class_get_pad_template (klass, "src_%02d");
135 for (n = 0; n < num; n++) {
136 padname = g_strdup_printf ("src_%02d", n);
137 pad = gst_pad_new_from_template (templ, padname);
140 /* here, you would set _getcaps () and _link () functions */
142 gst_element_add_pad (element, pad);
143 filter->srcpadlist = g_list_append (filter->srcpadlist, pad);
147 /* and now, simply parse each line and push over */
148 if (!(buf = gst_my_filter_getline (filter))) {
149 GstEvent *event = gst_event_new (GST_EVENT_EOS);
152 for (padlist = srcpadlist;
153 padlist != NULL; padlist = g_list_next (padlist)) {
154 pad = GST_PAD (padlist->data);
155 gst_event_ref (event);
156 gst_pad_push (pad, GST_DATA (event));
158 gst_event_unref (event);
159 gst_element_set_eos (element);
164 /* parse stream number and go beyond the ':' in the data */
165 num = atoi (GST_BUFFER_DATA (buf));
166 if (num >= 0 && num < g_list_length (filter->srcpadlist)) {
167 pad = GST_PAD (g_list_nth_data (filter->srcpadlist, num);
169 /* magic buffer parsing foo */
170 for (n = 0; GST_BUFFER_DATA (buf)[n] != ':' &&
171 GST_BUFFER_DATA (buf)[n] != '\0'; n++) ;
172 if (GST_BUFFER_DATA (buf)[n] != '\0') {
175 /* create subbuffer that starts right past the space. The reason
176 * that we don't just forward the data pointer is because the
177 * pointer is no longer the start of an allocated block of memory,
178 * but just a pointer to a position somewhere in the middle of it.
179 * That cannot be freed upon disposal, so we'd either crash or have
180 * a memleak. Creating a subbuffer is a simple way to solve that. */
181 sub = gst_buffer_create_sub (buf, n + 1, GST_BUFFER_SIZE (buf) - n - 1);
182 gst_pad_push (pad, GST_DATA (sub));
185 gst_buffer_unref (buf);
189 Note that we use a lot of checks everywhere to make sure that the content
190 in the file is valid. This has two purposes: first, the file could be
191 erronous, in which case we prevent a crash. The second and most important
192 reason is that - in extreme cases - the file could be used maliciously to
193 cause undefined behaviour in the plugin, which might lead to security
194 issues. <emphasis>Always</emphasis> assume that the file could be used to
199 <sect1 id="section-reqpad-request" xreflabel="Request pads">
200 <title>Request pads</title>
202 <quote>Request</quote> pads are similar to sometimes pads, except that
203 request are created on demand of something outside of the element rather
204 than something inside the element. This concept is often used in muxers,
205 where - for each elementary stream that is to be placed in the output
206 system stream - one sink pad will be requested. It can also be used in
207 elements with a variable number of input or outputs pads, such as the
208 <classname>tee</classname> (multi-output), <classname>switch</classname>
209 or <classname>aggregator</classname> (both multi-input) elements. At the
210 time of writing this, it is unclear to me who is responsible for cleaning
211 up the created pad and how or when that should be done. Below is a simple
212 example of an aggregator based on request pads.
215 static GstPad * gst_my_filter_request_new_pad (GstElement *element,
216 GstPadTemplate *templ,
220 gst_my_filter_base_init (GstMyFilterClass *klass)
222 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
223 static GstStaticPadTemplate sink_factory =
224 GST_STATIC_PAD_TEMPLATE (
228 GST_STATIC_CAPS ("ANY")
231 gst_element_class_add_pad_template (klass,
232 gst_static_pad_template_get (&sink_factory));
236 gst_my_filter_class_init (GstMyFilterClass *klass)
238 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
240 element_class->request_new_pad = gst_my_filter_request_new_pad;
244 gst_my_filter_request_new_pad (GstElement *element,
245 GstPadTemplate *templ,
249 GstMyFilterInputContext *context;
251 context = g_new0 (GstMyFilterInputContext, 1);
252 pad = gst_pad_new_from_template (templ, name);
253 gst_element_set_private_data (pad, context);
255 /* normally, you would set _link () and _getcaps () functions here */
257 gst_element_add_pad (element, pad);
263 The <function>_loop ()</function> function is the same as the one given
264 previously in <xref linkend="section-loopfn-multiinput"/>.