summaryrefslogtreecommitdiff
path: root/docs/design/part-gstghostpad.txt
blob: 9196774058cdc28705af964e81bcdbdccc338f3c (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
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
Ghostpads
---------

GhostPads are used to build complex compound elements out of
existing elements. They are used to expose internal element pads
on the complex element.

Some design requirements

  - Must look like a real GstPad on both sides.
  - target of Ghostpad must be changeable
  - target can be initially NULL

* a GhostPad is implemented using a private GstProxyPad class:


   GstProxyPad
   (------------------)
   | GstPad           |
   |------------------|
   | GstPad *target   |
   (------------------)
   | GstPad *internal |
   (------------------)


   GstGhostPad
   (------------------)   -\
   | GstPad           |    |
   |------------------|    |              
   | GstPad *target   |     > GstProxyPad
   |------------------|    |
   | GstPad *internal |    |
   |------------------|   -/
   | <private data>   |     
   (------------------)     

  A GstGhostPad (X) is _always_ created together with a GstProxyPad (Y). 
  The internal pad pointers are set to point to the eachother. The 
  GstProxyPad pairs have opposite directions, the GstGhostPad has the same
  direction as the (future) ghosted pad (target).


	(- X --------)
	|            |
	| target *   |
	|------------|
        | internal *----+   
	(------------)  |
          ^             V
	  |  (- Y --------)
	  |  |            |
	  |  | target *   |
	  |  |------------|
          +----* internal |     
	     (------------)

  Which we will abreviate to:

	(- X --------)      
	|            |     
	| target *--------->//
	(------------)     
             |            
 	    (- Y --------) 
  	    | target *----->//
	    (------------)

  The GstGhostPad (X) is also set as the parent of the GstProxyPad (Y).

  The target is a pointer to the internal pads peer. It is an optimisation to
  quickly get to the peer of a ghostpad without having to dereference the
  internal->peer.

  Some use case follow with a description of how the datastructure
  is modified.


* Creating a ghostpad with a target:

   gst_ghost_pad_new (char *name, GstPad *target)

   1) create new GstGhostPad X + GstProxyPad Y
   2) X name set to @name
   3) X direction is the same as the target, Y is opposite.
   4) the target of X is set to @target
   5) Y is linked to @target
   6) link/unlink and activate functions are set up
      on GstGhostPad.


                                      (--------------
	(- X --------)                |
	|            |                |------)
	| target *------------------> | sink |
	(------------)       -------> |------)
             |              /         (--------------
 	    (- Y --------) / (pad link)
      //<-----* target   |/      
	    (------------)
	
   - Automatically takes same direction as target.
   - target is filled in automatically.


* Creating a ghostpad without a target

   gst_ghost_pad_new_no_target (char *name, GstPadDirection dir)

   1) create new GstGhostPad X + GstProxyPad Y
   2) X name set to @name
   3) X direction is @dir
   5) link/unlink and activate functions are set up
      on GstGhostPad.

	(- X --------)      
	|            |     
	| target *--------->//
	(------------)     
             |            
 	    (- Y --------) 
  	    | target *----->//
	    (------------)

   - allows for setting the target later


* Setting target on an untargetted unlinked ghostpad

   gst_ghost_pad_set_target (char *name, GstPad *newtarget)

	(- X --------)      
	|            |     
	| target *--------->//
	(------------)     
             |            
 	    (- Y --------) 
  	    | target *----->//
	    (------------)

   1) assert direction of newtarget == X direction
   2) target is set to newtarget
   3) internal pad Y is linked to newtarget

                                      (--------------
	(- X --------)                |
	|            |                |------)
	| target *------------------> | sink |
	(------------)       -------> |------)
             |              /         (--------------
 	    (- Y --------) / (pad link)
      //<-----* target   |/      
	    (------------)

* Setting target on a targetted unlinked ghostpad

   gst_ghost_pad_set_target (char *name, GstPad *newtarget)

                                      (--------------
	(- X --------)                |
	|            |                |-------)
	| target *------------------> | sink1 |
	(------------)       -------> |-------)
             |              /         (--------------
 	    (- Y --------) / (pad link)
      //<-----* target   |/      
	    (------------)

   1) assert direction of newtarget (sink2) == X direction
   2) unlink internal pad Y and oldtarget
   3) target is set to newtarget (sink2)
   4) internal pad Y is linked to newtarget

                                      (--------------
	(- X --------)                |
	|            |                |-------)
	| target *------------------> | sink2 |
	(------------)       -------> |-------)
             |              /         (--------------
 	    (- Y --------) / (pad link)
      //<-----* target   |/      
	    (------------)

* Linking a pad to an untargetted ghostpad:

  gst_pad_link (src, X)

	      (- X --------)      
	      |            |     
	      | target *--------->//
	      (------------)     
                   |            
 	          (- Y --------) 
  	          | target *----->//
	          (------------)
     -------)
            |
      (-----|
      | src |
      (-----|
     -------)

     X is a sink GstGhostPad without a target. The internal GstProxyPad Y has
     the same direction as the src pad (peer).

    1) link function is called
      a) Y direction is same as @src
      b) Y target is set to @src
      c) Y is activated in the same mode as X
      d) core makes link from @src to X


                         (- X --------)
                         |            |
                         | target *----->//
                        >(------------)
       (real pad link) /      |
                      /      (- Y ------)
                     /    -----* target |
          -------)  /    /   (----------)
                 | /    /                 
           (-----|/    /                  
           | src |<----                    
           (-----|                            
          -------)


* Linking a pad to a targetted ghostpad:

    gst_pad_link (src, X)

                                                 (--------
                         (- X --------)          |
                         |            |          |------)
                         | target *------------->| sink |
                         (------------)         >|------)
                                    |          / (--------
                                    |         /
                                    |        /
          -------)                  |       / (real pad link)
		 |            (- Y ------) /
           (-----|            |          |/
           | src |       //<----* target |
           (-----|            (----------)
          -------)


    1) link function is called
      a) Y direction is same as @src
      b) Y target is set to @src
      c) Y is activated in the same mode as X
      d) core makes link from @src to X

                                                 (--------
                         (- X --------)          |
                         |            |          |------)
                         | target *------------->| sink |
                        >(------------)         >|------)
       (real pad link) /            |          / (--------
                      /             |         /
                     /              |        /
          -------)  /               |       / (real pad link)
		 | /          (- Y ------) /
           (-----|/           |          |/
           | src |<-------------* target |
           (-----|            (----------)
          -------)


* Setting target on untargetted linked ghostpad:

   gst_ghost_pad_set_target (char *name, GstPad *newtarget)

                                      
                         (- X --------)
                         |            | 
                         | target *------>//
                        >(------------)
       (real pad link) /            |
                      /             |
                     /              |
          -------)  /               |
		 | /          (- Y ------)
           (-----|/           |          |
           | src |<-------------* target |
           (-----|            (----------)
          -------)

   1) assert direction of @newtarget == X direction
   2) X target is set to @newtarget
   3) Y is linked to @newtarget

                                                 (--------
                         (- X --------)          |
                         |            |          |------)
                         | target *------------->| sink |
                        >(------------)         >|------)
       (real pad link) /            |          / (--------
                      /             |         /
                     /              |        /
          -------)  /               |       / (real pad link)
		 | /          (- Y ------) /
           (-----|/           |          |/
           | src |<-------------* target |
           (-----|            (----------)
          -------)

* Setting target on targetted linked ghostpad:

   gst_ghost_pad_set_target (char *name, GstPad *newtarget)

                                                 (--------
                         (- X --------)          |
                         |            |          |-------)
                         | target *------------->| sink1 |
                        >(------------)         >|-------)
       (real pad link) /            |          / (--------
                      /             |         /
                     /              |        /
          -------)  /               |       / (real pad link)
		 | /          (- Y ------) /
           (-----|/           |          |/
           | src |<-------------* target |
           (-----|            (----------)
          -------)

   1) assert direction of @newtarget == X direction
   2) Y and X target are unlinked
   2) X target is set to @newtarget
   3) Y is linked to @newtarget

                                                 (--------
                         (- X --------)          |
                         |            |          |-------)
                         | target *------------->| sink2 |
                        >(------------)         >|-------)
       (real pad link) /            |          / (--------
                      /             |         /
                     /              |        /
          -------)  /               |       / (real pad link)
		 | /          (- Y ------) /
           (-----|/           |          |/
           | src |<-------------* target |
           (-----|            (----------)
          -------)


Activation
~~~~~~~~~~

Sometimes ghost pads should proxy activation functions. This thingie
attempts to explain how it should work in the different cases.

  +---+     +----+                             +----+       +----+
  | A +-----+ B  |                             | C  |-------+ D  |
  +---+     +---=+                             +=---+       +----+
              +--=-----------------------------=-+
              |  +=---+   +----+  +----+  +---=+ |
              |  | a  +---+ b  ====  c +--+ d  | |
              |  +----+   +----+  +----+  +----+ |
              |                                  |
              +----------------------------------+
              state change goes from right to left
     <-----------------------------------------------------------

All of the labeled boxes are pads. The dashes (---) show pad links, and
the double-lines (===) are internal connections. The box around a, b, c,
and d is a bin. B and C are ghost pads, and a and d are proxy pads. The
arrow represents the direction of a state change algorithm. Not counting
the bin, there are three elements involved here -- the parent of D, the
parent of A, and the parent of b and c.

Now, in the state change from READY to PAUSED, assuming the pipeline
does not have a live source, all of the pads will end up activated at
the end. There are 4 possible activation modes:

  1) AD and ab in PUSH, cd and CD in PUSH
  2) AD and ab in PUSH, cd and CD in PULL
  3) AD and ab in PULL, cd and CD in PUSH
  4) AD and ab in PULL, cd and CD in PULL

When activating (1), the state change algorithm will first visit the
parent of D and activate D in push mode. Then it visits the bin. The bin
will first change the state of its child before activating its pads.
That means c will be activated in push mode. [*] At this point, d and C
should also be active in push mode, because it could be that activating
c in push mode starts a thread, which starts pushing to pads which
aren't ready yet. Then b is activated in push mode. Then, the bin
activates C in push mode, which should already be in push mode, so
nothing is done. It then activates B in push mode, which activates b in
push mode, but it's already there, then activates a in push mode as
well. The order of activating a and b does not matter in this case.
Then, finally, the state change algorithm moves to the parent of A,
activates A in push mode, and dataflow begins.

[*] Not yet implemented.

Activation mode (2) is implausible, so we can ignore it for now. That
leaves us with the rest.

(3) is the same as (1) until you get to activating b. Activating b will
proxy directly to activating a, which will activate B and A as well.
Then when the state change algorithm gets to B and A it sees that they
are already active, so it ignores them.

Similarly in (4), activating D will cause the activation of all of the
rest of the pads, in this order: C d c b a B A. Then when the state
change gets to the other elements they are already active, and in fact
data flow is already occuring.

So, from these scenarios, we can distill how ghost pad activation
functions should work:

Ghost source pads (e.g. C):
  push:
    called by: element state change handler
    behavior: just return TRUE
  pull:
    called by: peer's activatepull
    behavior: change the internal pad, which proxies to its peer e.g. C
        changes d which changes c.

Internal sink pads (e.g. d):
  push: 
    called by: nobody (doesn't seem possible)
    behavior: n/a
  pull:
    called by: ghost pad
    behavior: proxy to peer first

Internal src pads (e.g. a):
  push:
    called by: ghost pad
    behavior: activate peer in push mode
  pull:
    called by: peer's activatepull
    behavior: proxy to ghost pad, which proxies to its peer (e.g. a
        calls B which calls A)

Ghost sink pads (e.g. B):
  push:
    called by: element state change handler
    behavior: change the internal pad, which proxies to peer (e.g. B
        changes a which changes b)
  pull:
    called by: internal pad
    behavior: proxy to peer


It doesn't really make sense to have activation functions on proxy pads
that aren't part of a ghost pad arrangement.