summaryrefslogtreecommitdiff
path: root/docs/random/omega/caps2
blob: 69abc0cf152ca8ce2a8f50d00b11930ded4e9c28 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
The elementfactory for a given element will contain some information about the capabilities of element's
pads or potential pads.  An indication will be provided as to whether the pad always exists, always
exists once data is present, or *might* exist once data is present (the latter case is for things like
the MPEG system parsers, where an audio stream might or might not exist).


First, an entirely normal example:
----------------------------------

(-----------)        (----------)        (-------------)
! disksrc   !        ! mpg123   !        ! audiosink   !
!         src        sink     src        sink          !
!           !        !          !        !             !
(-----------)        (----------)        (-------------)

We start with only the disksrc.  The typefind filter is attached to the disksrc, and via typefind magic
the properties of the disksrc are found to be:

  disksrc->src->caps = {
    "audio/mp3",
    "layer",   GST_CAPS_INT (3),
    "bitrate", GST_CAPS_INT (128),
    NULL
  };

A look through the plugin registry shows that we have an element called mpg123 that has the following
caps:

  static GstCapsFactory mpg123_sink_caps = {
    "audio/mp3",
    "layer",   GST_CAPS_INT_RANGE (1, 3),
    "bitrate", GST_CAPS_INT_RANGE (8, 320),
    NULL
  };

The caps of the disksrc fit within those parameters, so we instantiate an mpg123 and attach it to the
disksrc.  The connection succeeds negotiation and as a result the mpg123 specifies its output caps as:

  mpg123->src->caps = {
    "audio/raw",
    "format",   GST_CAPS_BITFIELD (S16),
    "depth",    GST_CAPS_INT (16),
    "rate",     GST_CAPS_INT (44100),
    "channels", GST_CAPS_INT (2),
    NULL
  };

Again from the plugin registry we find an element audiosink that has appropriate caps:

  static GstCapsFactory audiosink_src_caps = {
    "audio/raw",
    "format",   GST_CAPS_BITFIELD (S16,....),
    "depth",    GST_CAPS_INT (16),
    "rate",     GST_CAPS_INT_RANGE (4000, 96000),
    "channels", GST_CAPS_INT_RANGE (1, 2),
    NULL
  };

A copy of the audiosink is instantiated and attached, negotiation goes smoothly, and we're done.  No
dataflow has occured, no failure found, etc.  An ideal autoplug.


Now, a slightly more convoluted example:
----------------------------------------

Start with the same graph:

(-----------)        (----------)        (-------------)
! disksrc   !        ! mpg123   !        ! audiosink   !
!         src        sink     src        sink          !
!           !        !          !        !             !
(-----------)        (----------)        (-------------)

Run typefind on the disksrc's output, get the same output caps:

  disksrc->src->caps = {
    "audio/mp3",
    "layer",   GST_CAPS_INT (3),
    "bitrate", GST_CAPS_INT (128),
    NULL
  };

Find and attach mpg123, get the following output caps this time:

  mpg123->src->caps = {
    "audio/raw",
    "format",   GST_CAPS_BITFIELD (S16),
    "depth",    GST_CAPS_INT (16),
    "rate",     GST_CAPS_INT (44100),
    "channels", GST_CAPS_INT (1),
    NULL
  };

Note that this time we have a mono output.  A look into the audiosink caps shows that we have a match.
So we instantiate a copy.  Oops.  We now find that the caps for the input pad on our audiosink have
changed:

  mpg123->src->caps = {
    "audio/raw",
    "format",   GST_CAPS_BITFIELD (S16,...),
    "depth",    GST_CAPS_INT (16),
    "rate",     GST_CAPS_INT (11025, 48000),
    "channels", GST_CAPS_INT (2),
    NULL
  };

Whoops.  It seems that the sound card we've got in this machine (FIXME how on earth to deal with
multiple sound cards???) doesn't support mono output *at all*.  This is a problem.  We now find that we
hae no options as far as directly matching the mpg123 to the audiosink.

A look through our (ficticious) plugin registry shows at least one element that at least has audio/raw
on both input and ouput (since both mpg123 and audiosink have open pads with this mime type).  A closerlook shows that its caps are:

  static GstCapsFactory mono2stereo_sink_caps = {
    "audio/raw",
    "channels", GST_CAPS_INT (1),
    NULL
  };
  static GstCapsFactory mono2stereo_src_caps = {
    "audio/raw",
    "channels", GST_CAPS_INT (2),
    NULL
  };

Wow, that's a perfect match.  Instantiate, attach to mpg123, no problems.  Attach to audiosink, no
problems.  Done.  When we start up the pipeline, we should get absolutely no callbacks from pads saying
"help me, I've fallen and..., er, I don't like this buffer!".


A really messy case:
--------------------

Start with a disksrc, typefind it, get the following:

  disksrc->src->caps = {
    "audio/mp3",
    "layer",   GST_CAPS_INT (3),
    "bitrate", GST_CAPS_INT (128),
    NULL
  };

Look through the plugin registry, find mpg123.  Instantiate it, attach it.  It spits out audio
parameters as usual:

  mpg123->src->caps = {
    "audio/raw",
    "format",   GST_CAPS_BITFIELD (S16),
    "depth",    GST_CAPS_INT (16),
    "rate",     GST_CAPS_INT (44100),
    "channels", GST_CAPS_INT (2),
    NULL
  };

Now we instantiate an audiosink plugin.  This time, we're sunk:

  mpg123->src->caps = {
    "audio/raw",
    "format",   GST_CAPS_BITFIELD (S8,U8),
    "depth",    GST_CAPS_INT (8),
    "rate",     GST_CAPS_INT_RANGE (11025, 22050),
    "channels", GST_CAPS_INT (1),
    NULL
  };

ACK!  It's one of those Disney Sound Source things.  We've got a problem here that isn't obviously
solvable.  However, there happens to be another mp3 decoder sitting around.  It's got the same
properties as mpg123, but a lower merit value.  Let's instantiate one and attach it.  We get the
following output pad caps:

  mp3decoder->src->caps = {
    "audio/raw",
    "format",   GST_CAPS_BITFIELD (S8,S16),
    "depth",    GST_CAPS_INT_RANGE (8,16),
    "rate",     GST_CAPS_INT_RANGE (8000, 44100),
    "channels", GST_CAPS_INT (1,2),
    NULL
  };

Well, that matches the audiosink.  We try attaching it, and during negotiation the mp3decoder finds
sufficient common ground with the castrated audiosink and sets its output pad to match the best of the
options: S8 at 22050 KHz.



Next to impossible scenario: DVD
--------------------------------

Start with a dvdsrc.  It's output pad caps are:

  static GstCapsFactory dvdsrc_src_caps = {
    "video/mpeg",
    "mpegversion",  GST_CAPS_INT (2),
    "systemstream", GST_CAPS_BOOLEAN (TRUE),
    NULL
  };

The type would be classified as incomplete via some mechanism.  This might cause the autoplug code to go
and run the typefind function.  It would flesh the type out to the following:

  dvdsrc->src->caps = {
    "video/mpeg",
    "mpegversion",  GST_CAPS_INT (2),
    "systemstream", GST_CAPS_BOOLEAN (TRUE),
    "videostreams", GST_CAPS_INT (1),
    "audiostreams", GST_CAPS_INT (3),
    "bitrate",      GST_CAPS_INT (40960),
    NULL,
  };

Wow, that helped a lot.  A check through the plugin registry shows that the mpeg2parse will match those
properties:

  static GstCapsFactory mpeg2parse_sink_caps = {
    "video/mpeg",
    "mpegversion",  GST_CAPS_INT (2),
    "systemstream", GST_CAPS_BOOLEAN (TRUE),
    NULL
  };

(In retrospect, it may not be necessary to run typefind if there's match this good right away.  Only run
typefind when there's no exact match.)
Since there are no output pads yet, we have to actually push data through the pipeline.  The moment a
buffer or two get to the mpeg2parse element, it promptly goes and creates an output pad, probably of the
following caps:

  mpeg2parse_video_src_caps = {
    "video/mpeg",
    "mpegversion",  GST_CAPS_RANGE (1,2),
    "systemstream", GST_CAPS_BOOLEAN (FALSE),
    NULL
  };

This seems to be a task for typefind again.  But since data is flowing, we have to be careful with the
buffers.  (This is the case in any typefind maneuver, but moreso when one really can't rewind the
source without consequences)  The autoplug system attaches a special pseudo-element to mpeg2parse's new
output pad, and attaches the typefind element to the end of that.  The pseudo-element takes the buffer,
stores it, and passes a copy off to the attached element, in this case typefind.  This repeats until
typefind has determined the type, at which point the typefind is removed, and the newly found element is
attached instead.

The pseudo-element is 'rewound' and the stored buffers flow out and into the newly attached element.
When the cache of buffers is gone, a signal fires and the autoplug system removes the pseudo-element and
reconnects the pipeline.

In this case, the typefind function will find the following:

  mpeg2parse_video_src_caps = {
    "video/mpeg",
    "mpegversion",  GST_CAPS_INT (2),
    "systemstream", GST_CAPS_BOOLEAN (FALSE),
    "bitrate",      GST_CAPS_INT (36864),
    "width",        GST_CAPS_INT (720),
    "height",       GST_CAPS_INT (480),
    "framerate",    GST_CAPS_FLOAT (29.97002997),
    "chromaformat", GST_CAPS_INT (1),		[GST_CAPS_STRING ("4:2:0") ?]
    NULL
  };

Back to the plugin registry, we find our only choice is mpeg2dec, which has input caps of:

  static GstCapsFactory mpeg2dec_sink_caps = {
    "video/mpeg",
    "mpegversion",  GST_CAPS_RANGE (1,2),
    "systemstream", GST_CAPS_BOOLEAN (FALSE),
    NULL
  };

Once again it just so happens that we really didn't need to do the typefind at all.  But it can't hurt
unless the typefind is slow and painful, which we can guess won't be the case since the choices are
rather limited by the fact that there's already a MIME type attached, meaning we can drastically reduce
the number of typefind functions we try (down to one, actually).

However, since we *have* run the typefind, upon attachment of the input pad of mpeg2dec, the output pad
looks like the following:

  mpeg2dec_src_caps = {
    "video/raw",
    "fourcc",    GST_CAPS_LIST (
			GST_CAPS_FOURCC ("YV12"),	[identical...]
			GST_CAPS_FOURCC ("IYUV"),
			GST_CAPS_FOURCC ("I420"),
                 ),
    "width",     GST_CAPS_INT (720),
    "height",    GST_CAPS_INT (480),
    "framerate", GST_CAPS_FLOAT (29.97002997),
    NULL
  };

Currently only videosink supports the output of video/raw.  It claims a list of FOURCCs but nothing
more:

  static GstCapsFactory videosink_sink_caps = {
    "video/raw",
    "fourcc", GST_CAP_LIST ( GST_CAPS_FOURCC ("YV12"),
		GST_CAPS_FOURCC ("IYUV"), GST_CAPS_FOURCC ("I420"),
		GST_CAPS_FOURCC ("YUY2"), GST_CAPS_FOURCC ("UYVY"),
		[ etc... ],
              ),
    NULL
  };

When instantiated, we potentially have the same problem as with the audiosink: we don't necessarily know
which hardware output to use.  Somehow we have to solve the problem of setting some element arguments
before we can get useful information out of them as to the properties.  In this case anyway, if the
videosink were to find only one output possibility, it would trim the list of FOURCCs it can deal with
to what the hardware can handle, as well as add further properties:

  videosink_sink_caps = {
    "video/raw",
    "fourcc", GST_CAPS_LIST (GST_CAPS_FOURCC ("YV12"),
			GST_CAPS_FOURCC ("YUY2"),
              ),
    "width",  GST_CAPS_INT_RANGE (4,1020),
    "height", GST_CAPS_INT_RANGE (4,1020),
    NULL
  };

We can now connect the mpeg2dec output to the videosink, and we now have displaying video.

. . . .