Git init
[framework/multimedia/gstreamer0.10.git] / docs / pwg / other-ntoone.xml
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>
4   <para>
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 passwed 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
16     this.
17   </para>
18   <para>
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
23     yourself.
24   </para>
25
26 <!--
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>
31     <para>
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.
39     </para>
40     <para>
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.
59     </para>
60     <para>
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
66       (not shown).
67     </para>
68     <programlisting>
69 static GstPadLinkReturn
70 gst_avi_mux_audio_link (GstPad        *pad,
71                         const GstCaps *caps)
72 {
73   GstAviMux *mux = GST_AVI_MUX (gst_pad_get_parent (pad));
74   GstStructure *str = gst_caps_get_structure (caps, 0);
75   const gchar *mime = gst_structure_get_name (str);
76
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). */
81     [..]
82     return GST_PAD_LINK_OK;
83   } else if !strcmp (str, "audio/x-raw-int")) {
84     /* See above, but now with the raw audio tag (0x0001). */
85     [..]
86     return GST_PAD_LINK_OK;
87   } else [..]
88 [..]
89 }
90
91 static void
92 gst_avi_mux_loop (GstElement *element)
93 {
94   GstAviMux *mux = GST_AVI_MUX (element);
95 [..]
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);
102     GList *item;
103
104     for (item = padlist; item != NULL; item = item->next) {
105       GstPad *pad = item->data;
106       GstCaps *caps;
107
108       if (!GST_PAD_IS_SINK (pad))
109         continue;
110
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,
122                         NULL);
123             break;
124           case 0x0001: /* pcm */
125             caps = gst_caps_new_simple ("audio/x-raw-int",
126                                         [..]);
127             break;
128           [..]
129         }
130       } else if (!strncmp (gst_pad_get_name (pad), "video_", 6)) {
131         [..]
132       } else {
133         g_warning ("oi!");
134         continue;
135       }
136
137       /* set static caps */
138       gst_pad_use_explicit_caps (pad);
139       gst_pad_set_explicit_caps (pad, caps);
140     }
141   }
142 [..]
143   /* Next runs will never be the first again. */
144   mux->first_cycle = FALSE;
145 }
146     </programlisting>
147     <para>
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.
152     </para>
153   </sect1>
154 -->
155 </chapter>