tee: Check for the removed pad flag also in the slow pushing path
[platform/upstream/gstreamer.git] / docs / random / interfaces
1 INTERFACES & ELEMENTS
2 ---------------------
3
4 1) Introduction
5 ===============
6 Interfaces are descriptions on how to handle an object, without actually
7 implementing the object. This allows for multiple objects to be instantiated
8 based on this interface. Each of them can then be handled equally by an
9 application.
10 Glib, apparently (unchecked), has a way of creating interfaces, probably
11 by means of a class struct without actually defining the object. The object,
12 then, does not define a class and these two add up. Benjamin knows more
13 about interfaces, I didn't study interfaces & glib too deeply, yet. I know
14 them just from Java.
15 Interfaces are cool! It allows for some sort of random element creation
16 without needing to link to the implementation. This is similar to how
17 GStreamer currently handles media plugins. GStreamer itself could be seen
18 as an interface too, in that respect.
19
20 2) So why do we need interfaces?
21 ================================
22 Because GStreamer doesn't handle it all. GStreamer in itself is a media
23 framework for streams of data from one element to the next. There's lots
24 of things that's media-related, but not handled in this description.
25 Several examples will probably clarify this: think of the Xvideo output
26 plugin. We can create an overlay here (Xv-based), and we currently control
27 this X-connection using glib properties. However, what property name is
28 associated with what control? And does it work the same as v4lsrc's
29 overlay image control?
30 The same goes for a mixer, for image control, audio control, and probably
31 a lot more. The general idea is simple: *this needs to be documented*.
32 But properties aren't all - they simply cannot do this all. Some things
33 cannot be described in a simple one-argument property thing. Of course,
34 we could give a pointer to a struct as argument, but that's merely a hack
35 and requires both plugin and app to know the ABI of the struct. This
36 kills the whole idea of making the plugin independent of the app.
37 In short: we want interfaces for this.
38
39 3) How to integrate an interface in GStreamer
40 =============================================
41 Let us start with some starting point: an interface is associated
42 with an element. It is a feature exported by that specific element,
43 not by a pipeline or anything more complex. Pipelines are already
44 handled just fine by GStreamer (or you wouldn't be reading all
45 this).
46 Obviously, a pipeline can be a fallback for an interface. Imagine
47 that we're looking for an audio sink that exposes a mixer, but our
48 fakesink audio output doesn't ("I wonder why"). We could then create
49 a pipeline with the volume element in it to "fake" a mixer. Ideally,
50 the volume element would implement a mixer interface itself.
51
52 How are we going to do that in programmatic way? We currently use
53 properties. Their huge advantage is that we do not need to care
54 about adding new functions or whatever. Their disadvantage is that
55 they're limited to one argument. Anything more complex requires
56 app/plugin knowledge about the shared data, and that defeats the
57 point of them: to have no dependency on each other. This could be
58 solved partially by using action signals, but that makes the whole
59 picture quite complex (since you use multiple methods for doing one
60 simple thing). Also, they are quite slow compared to functions
61 because of the table lookups. In short: it'd work, but I'm not in
62 facour of it...
63 OK, so an element exposes interfaces. This allows us to think of
64 the idea of embedding interfaces (dynamically, of course) in the
65 GstElement object. Think of an object being able to register an
66 indefinate number of interfaces per object instance, and a client
67 application could then enumerate interfaces and instantiate one.
68 Glib gives us GInterface for this purpose. The disadvantage of
69 this is that it's on a per-class basis, not a per-instance basis.
70 This is a problem in case of elements where it depends on several
71 properties whether it supports an interface or not. This can be
72 solved by simply making one generic virtual function "supported ()"
73 in a generic derived object of GInterface (GstInterface?).
74
75 GstInterface is then a generic thing that is inherited by specific
76 interfaces (see examples). Obviously, the client will need to know
77 about the ABI/API of this struct, but that'll happen either way.
78 Surely, there needs to binary linkage, but I don't consider that a
79 bad thing. It does improve performance compared to action signals!
80
81 So an element contains interfaces. But where are these interfaces
82 described? And who creates them? I suggest that we do that just as
83 we handle gstvideo and gstaudio right now (these libs do *nothing*
84 useful currently, so this'd make them a lot more interesting).
85 These interfaces inherit from GstInterface. The functions that
86 are needed, can be provided through a class object. The element is
87 then responsible for storing variables and so on. gstvideo/audio
88 provides wrapper functions for the class functions. That's also how
89 glib suggest us to use GInterfaces.
90
91 Plugin and application then handle and retrieve interfaces as
92 documented in the glib documentation, which is available at:
93 http://www.gnome.org/~mathieu/gobject/main.html
94
95 So the most important part left is to document the interfaces
96 and make sure all elements exporting them work equally. For this,
97 I'll give two examples.
98
99 4) Examples
100 ===========
101
102 /* This small extra virtual function is here to provide an
103  * interface functionality on a per-instance basis rather
104  * than a per-class basis, which is the case for glib.
105  */
106 typedef struct _GstInterfaceClass {
107   GTypeInterface parent;
108
109   /* virtual functions */
110   gboolean (* supported) (GstInterface *iface);
111 } GstInterfaceClass;
112
113 There would probably be a convenience function that checks
114 a specific interface's implementation (glib allows for this)
115 and checks for ->supported () to be set and to return TRUE:
116
117 gboolean
118 gst_element_implements_interface (GstElement *element,
119                                   GType       iface_type)
120 {
121   if (G_TYPE_CHECK_INSTANCE_TYPE (G_OBJECT (element),
122                                   type)) {
123     GstInterface *iface;
124     GstInterfaceClass *ifclass;
125
126     iface = G_TYPE_CHECK_INSTANCE_CAST (G_OBJECT (element),
127                                         type, GstInterface)
128     ifclass = GST_INTERFACE_GET_CLASS (iface);
129
130     if (ifclass->supported != NULL &&
131         ifclass->supported (iface) == TRUE) {
132       return TRUE;
133     }
134   }
135
136   return FALSE;
137 }
138
139 Let's now add some functions so we can abuse this in case/check
140 functions.
141
142 GstInterface *
143 gst_interface_cast (gpointer from,
144                     GType    type)
145 {
146   GstInterface *iface;
147
148   /* check cast, give warning+fail if it's invalid */
149   if (!(iface = G_TYPE_CHECK_INSTANCE_CAST (G_OBJECT (element),
150                                             type, GstInterface))) {
151     return NULL;
152   }
153
154   /* if we're an element, take care that this interface
155    * is actually implemented */
156   if (GST_IS_ELEMENT (from)) {
157     gboolean interface_is_implemented =
158         gst_element_implements_interface (GST_ELEMENT (from),
159                                           type);
160     g_return_val_if_fail (interface_is_implemented == TRUE, NULL);
161   }
162
163   return iface;
164 }
165
166 gboolean
167 gst_interface_check (gpointer from,
168                      GType    type)
169 {
170   GstInterface *iface;
171
172   /* check cast, return FALSE if it fails, don't give a warning... */
173   if (!G_TYPE_CHECK_INSTANCE_CAST (from, type,
174                                    GstInterface)) {
175     return FALSE;
176   }
177
178   iface = G_TYPE_CHECK_INSTANCE_CAST (G_OBJECT (element),
179                                       type, GstInterface);
180
181   /* now, if we're an element (or derivative), is this thing
182    * actually implemented for real? */
183   if (GST_IS_ELEMENT (from)) {
184     if (!gst_element_implements_interface (GST_ELEMENT (from),
185                                            type)) {
186       return FALSE;
187     }
188   }
189
190   return TRUE;
191 }
192
193 #define GST_INTERFACE_CHECK_INSTANCE_CAST(obj, type, cast_t) \
194   ((cast_t *) gst_interface_cast ((obj), (type))
195 #define GST_INTERFACE_CHECK_INSTANCE_TYPE(obj, type) \
196   (gst_interface_check ((obj), (type))
197
198 We could use this in the GST_IS_... () macros. For example, the
199 macros GST_IS_MIXER () and GST_MIXER () would then look like this:
200
201 /* Note that this is a non-standard macro, and with a reason! */
202 #define GST_MIXER(obj) \
203   (GST_INTERFACE_CHECK_INSTANCE_CAST ((obj), \
204                                       GST_TYPE_MIXER,
205                                       GstMixer))
206 #define GST_IS_MIXER(obj) \
207   (GST_INTERFACE_CHECK_INSTANCE_TYPE ((obj), \
208                                       GST_TYPE_MIXER))
209
210 So the application would just tread it with the known macro, and
211 everything would look extremely simple to the end user.
212
213 4a) mixer
214 ---------
215 A mixer is a way of controlling volume and input/output channels.
216 This doesn't mean that you control which channel is the subwoofer,
217 all that is supposed to be done automatically. It is really meant
218 as a way of representing system-level volumes and such. It could
219 also be used to turn on/off certain outputs or inputs.
220 As you've noticed, I'm not only talking about output, but also
221 input. Indeed, I want both osssrc *and* osssink to export the
222 same mixer interface! Or at least a very similar one. Volume
223 control works the same for both. You could say that osssrc should
224 enumerate the input channels (such as microphone, line-in). Of
225 course, osssink should not. Or maybe it should, not sure... Maybe,
226 we'd need a parent osselement which implements all mixer channels.
227 And alsa* would surely implement the same interface.
228
229 /* This is confusing naming... (i.e. FIXME)
230  * A channel is referred to both as the number of simultaneous
231  * sound streams the input can handle as well as the in-/output
232  * itself
233  */
234
235 #define GST_MIXER_CHANNEL_INPUT  (1<<0)
236 #define GST_MIXER_CHANNEL_OUTPUT (1<<1)
237 #define GST_MIXER_CHANNEL_MUTE   (1<<2)
238 #define GST_MIXER_CHANNEL_RECORD (1<<3)
239
240 typedef struct _GstMixerChannel {
241   gchar *label;
242   gint   current_num_channels,
243          max_num_channels,
244          flags;
245 } GstMixerChannel;
246
247 typedef struct _GstMixerClass {
248   GTypeInterface klass;
249
250   /* virtual functions */
251   GList *  (* list_channels) (GstMixer        *mixer);
252
253   void     (* set_volume)    (GstMixer        *mixer,
254                               GstMixerChannel *channel,
255                               gint            *volumes);
256   void     (* get_volume)    (GstMixer        *mixer,
257                               GstMixerChannel *channel,
258                               gint            *volumes);
259
260   void     (* set_mute)      (GstMixer        *mixer,
261                               GstMixerChannel *channel,
262                               gboolean         mute);
263   void     (* set_record)    (GstMixer        *mixer,
264                               GstMixerChannel *channel,
265                               gboolean         record);
266 } GstMixerClass;
267
268 libgstmixer.la/so provides wrapper functions for each of the
269 class' virtual functions. Possibly also some macros for
270 GST_MIXER_CHANNEL_HAS_FLAG () or _get_channel ().
271
272 The rest is done automatically, as described in the already-
273 mentioned glib documentation for GInterface. This includes
274 things like the base_init () function of the GstMixerClass,
275 which fills all the virtual functions for the mixer, and the
276 actual function implementations. The mixer, basically, operates
277 as an element on its own. It gets the file descriptor from
278 the interface->element (every oss... is a osscommon, etc.).
279
280 4b) overlay
281 -----------
282 Overlay is used in both in- and output, too. Think of v4lsrc,
283 v4l2src, v4lmjpegsrc, xvideosink - all overlays. But where do
284 we position the overlay window? Control of this can be done at
285 various levels: locational control (over the server, asynchronous)
286 or XID control (but that makes you depend on X and limits the
287 ability to broaden it over to non-X elements such as fbsink).
288
289 However, simplicity *is* an issue here. Do we really care about
290 overlay? In the end, users will have to link against either FB
291 or X anyway, so we might want to create separate interfaces for
292 both. On the other hand, we want to be general too... This is a
293 decision that we need to make as early as possible in this process.
294 For now, I propose making X- and FB-based interfaces.
295
296 Let's assume that we take X as a basis. Then, overlay becomes as
297 simple as one function. Possible extendible by providing inputs
298 (like in the mixer) and norms, although that only applies to
299 input-to-analog, not to-digital... Others simply return NULL.
300
301 typedef struct _GstOverlayClass {
302   GTypeInterface klass;
303
304   /* virtual functions */
305   void    (* set_xwindowid) (GstOverlay        *overlay,
306                              XID                xid);
307 } GstOverlayClass;
308
309 That's all! It would look similar for FB & co.
310
311 4c) user input
312 --------------
313 And yes, user input could be an interface too. Even better, it
314 should definitely be. And wasn't this one of our key issues for
315 0.8.0?
316
317 No code here. Go implement it, lazy ass!
318
319 General ways of thinking: input can come from a plugin, or from
320 the application (we don't have modules for joystick input et all).
321 However, plugins handling input (such as dvdsrc) need to be able
322 to handle each. So we get both input-to-application as well as
323 input-from-application APIs.
324
325 5) Status of this document
326 ==========================
327 The interfaces are implemented, more (for metadata, framebuffer-
328 overlay, video balancing (brightness), user input etc. are all
329 pending.
330
331 6) Copyright and blabla
332 =======================
333 (c) Ronald Bultje, 2003 <rbultje@ronald.bitfreak.net> under the
334 terms of the GNU Free Documentation License. See http://www.gnu.org/
335 for details.
336
337 And no, I'm not for hire. ;).