1 <chapter id="chapter-other-ntoone"
2 xreflabel="Writing a N-to-1 Element or Muxer">
3 <title>Writing a N-to-1 Element or Muxer</title>
5 N-to-1 elements have been previously mentioned and discussed in both
6 <xref linkend="chapter-advanced-request"/> and in
7 <xref linkend="chapter-scheduling"/>. The main noteworthy thing
8 about N-to-1 elements is that each pad is push-based in its own thread,
9 and the N-to-1 element synchronizes those streams by
10 expected-timestamp-based logic. This means it lets all streams wait
11 except for the one that provides the earliest next-expected timestamp.
12 When that stream has passed one buffer, the next
13 earliest-expected-timestamp is calculated, and we start back where we
14 were, until all streams have reached EOS. There is a helper base class,
15 called <classname>GstCollectPads</classname>, that will help you to do
19 Note, however, that this helper class will only help you with grabbing
20 a buffer from each input and giving you the one with earliest timestamp.
21 If you need anything more difficult, such as "don't-grab-a-new-buffer
22 until a given timestamp" or something like that, you'll need to do this
27 Note: I'd like to have something like this in the final text, but since
28 the code below doesn't work and this is all 0.8'y, I commented it for now.
29 <sect1 id="section-muxer-negotiation" xreflabel="Negotiation">
30 <title>Negotiation</title>
32 Most container formats will have a fair amount of issues with
33 changing content on an elementary stream. Therefore, you should
34 not allow caps to be changed once you've started using data from
35 them. The easiest way to achieve this is by using explicit caps,
36 which have been explained before. However, we're going to use them
37 in a slightly different way then what you're used to, having the
38 core do all the work for us.
41 The idea is that, as long as the stream/file headers have not been
42 written yet and no data has been processed yet, a stream is allowed
43 to renegotiate. After that point, the caps should be fixed, because
44 we can only use a stream once. Caps may then only change within an
45 allowed range (think MPEG, where changes in FPS are allowed), or
46 sometimes not at all (such as AVI audio). In order to do that, we
47 will, after data retrieval and header writing, set an explicit caps
48 on each sink pad, that is the minimal caps describing the properties
49 of the format that may not change. As an example, for MPEG audio
50 inside an MPEG system stream, this would mean a wide caps of
51 audio/mpeg with mpegversion=1 and layer=[1,2]. For the same audio type
52 in MPEG, though, the samplerate, bitrate, layer and number of channels
53 would become static, too. Since the (request) pads will be removed
54 when the stream ends, the static caps will cease to exist too, then.
55 While the explicit caps exist, the <function>_link ()</function>-
56 function will not be called, since the core will do all necessary
57 checks for us. Note that the property of using explicit caps should
58 be added along with the actual explicit caps, not any earlier.
61 Below here follows the simple example of an AVI muxer's audio caps
62 negotiation. The <function>_link ()</function>-function is fairly
63 normal, but the <function>-Loop ()</function>-function does some of
64 the tricks mentioned above. There is no <function>_getcaps ()</function>-
65 function since the pad template contains all that information already
69 static GstPadLinkReturn
70 gst_avi_mux_audio_link (GstPad *pad,
73 GstAviMux *mux = GST_AVI_MUX (gst_pad_get_parent (pad));
74 GstStructure *str = gst_caps_get_structure (caps, 0);
75 const gchar *media = gst_structure_get_name (str);
77 if (!strcmp (str, "audio/mpeg")) {
78 /* get version, make sure it's 1, get layer, make sure it's 1-3,
79 * then create the 2-byte audio tag (0x0055) and fill an audio
80 * stream structure (strh/strf). */
82 return GST_PAD_LINK_OK;
83 } else if !strcmp (str, "audio/x-raw")) {
84 /* See above, but now with the raw audio tag (0x0001). */
86 return GST_PAD_LINK_OK;
92 gst_avi_mux_loop (GstElement *element)
94 GstAviMux *mux = GST_AVI_MUX (element);
96 /* As we get here, we should have written the header if we hadn't done
97 * that before yet, and we're supposed to have an internal buffer from
98 * each pad, also from the audio one. So here, we check again whether
99 * this is the first run and if so, we set static caps. */
100 if (mux->first_cycle) {
101 const GList *padlist = gst_element_get_pad_list (element);
104 for (item = padlist; item != NULL; item = item->next) {
105 GstPad *pad = item->data;
108 if (!GST_PAD_IS_SINK (pad))
111 /* set static caps here */
112 if (!strncmp (gst_pad_get_name (pad), "audio_", 6)) {
113 /* the strf is the struct you filled in the _link () function. */
114 switch (strf->format) {
115 case 0x0055: /* mp3 */
116 caps = gst_caps_new_simple ("audio/mpeg",
117 "mpegversion", G_TYPE_INT, 1,
118 "layer", G_TYPE_INT, 3,
119 "bitrate", G_TYPE_INT, strf->av_bps,
120 "rate", G_TYPE_INT, strf->rate,
121 "channels", G_TYPE_INT, strf->channels,
124 case 0x0001: /* pcm */
125 caps = gst_caps_new_simple ("audio/x-raw",
130 } else if (!strncmp (gst_pad_get_name (pad), "video_", 6)) {
137 /* set static caps */
138 gst_pad_use_explicit_caps (pad);
139 gst_pad_set_explicit_caps (pad, caps);
143 /* Next runs will never be the first again. */
144 mux->first_cycle = FALSE;
148 Note that there are other ways to achieve that, which might be useful
149 for more complex cases. This will do for the simple cases, though.
150 This method is provided to simplify negotiation and renegotiation in
151 muxers, it is not a complete solution, nor is it a pretty one.