part-gstghostpad.txt 14.8 KB
Newer Older
1 2 3
Ghostpads
---------

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

8
Some design requirements
9 10 11

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

14
* a GhostPad is implemented using a private GstProxyPad class:
15 16 17 18 19 20 21 22


   GstProxyPad
   (------------------)
   | GstPad           |
   |------------------|
   | GstPad *target   |
   (------------------)
23 24
   | GstPad *internal |
   (------------------)
25 26 27 28 29


   GstGhostPad
   (------------------)   -\
   | GstPad           |    |
30 31 32 33
   |------------------|    |              
   | GstPad *target   |     > GstProxyPad
   |------------------|    |
   | GstPad *internal |    |
34
   |------------------|   -/
35 36 37 38 39 40 41
   | <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).
42 43


44 45 46 47 48 49 50 51 52 53 54 55 56 57
	(- X --------)
	|            |
	| target *   |
	|------------|
        | internal *----+   
	(------------)  |
          ^             V
	  |  (- Y --------)
	  |  |            |
	  |  | target *   |
	  |  |------------|
          +----* internal |     
	     (------------)

Zhang Wanming's avatar
Zhang Wanming committed
58
  Which we will abbreviate to:
59 60 61 62 63 64 65 66 67 68

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

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

71 72 73 74
  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.

75 76 77 78 79 80 81 82
  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)

83
   1) create new GstGhostPad X + GstProxyPad Y
84
   2) X name set to @name
85 86 87
   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
88 89 90 91 92
   6) link/unlink and activate functions are set up
      on GstGhostPad.


                                      (--------------
93
	(- X --------)                |
94 95
	|            |                |------)
	| target *------------------> | sink |
96 97 98 99 100 101
	(------------)       -------> |------)
             |              /         (--------------
 	    (- Y --------) / (pad link)
      //<-----* target   |/      
	    (------------)
	
102 103 104 105 106 107
   - Automatically takes same direction as target.
   - target is filled in automatically.


* Creating a ghostpad without a target

108
   gst_ghost_pad_new_no_target (char *name, GstPadDirection dir)
109

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

116 117 118 119 120 121 122 123
	(- X --------)      
	|            |     
	| target *--------->//
	(------------)     
             |            
 	    (- Y --------) 
  	    | target *----->//
	    (------------)
124 125 126 127 128 129 130 131

   - allows for setting the target later


* Setting target on an untargetted unlinked ghostpad

   gst_ghost_pad_set_target (char *name, GstPad *newtarget)

132 133 134 135 136 137 138 139
	(- X --------)      
	|            |     
	| target *--------->//
	(------------)     
             |            
 	    (- Y --------) 
  	    | target *----->//
	    (------------)
140 141 142

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

145 146 147 148 149 150 151 152 153
                                      (--------------
	(- X --------)                |
	|            |                |------)
	| target *------------------> | sink |
	(------------)       -------> |------)
             |              /         (--------------
 	    (- Y --------) / (pad link)
      //<-----* target   |/      
	    (------------)
154

155
* Setting target on a targetted unlinked ghostpad
156 157 158

   gst_ghost_pad_set_target (char *name, GstPad *newtarget)

159 160 161 162 163 164 165 166 167 168 169 170 171 172
                                      (--------------
	(- 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
173

174 175 176 177 178 179 180 181 182
                                      (--------------
	(- X --------)                |
	|            |                |-------)
	| target *------------------> | sink2 |
	(------------)       -------> |-------)
             |              /         (--------------
 	    (- Y --------) / (pad link)
      //<-----* target   |/      
	    (------------)
183 184 185 186 187

* Linking a pad to an untargetted ghostpad:

  gst_pad_link (src, X)

188 189 190 191 192 193 194
	      (- X --------)      
	      |            |     
	      | target *--------->//
	      (------------)     
                   |            
 	          (- Y --------) 
  	          | target *----->//
195 196 197 198 199 200 201 202
	          (------------)
     -------)
            |
      (-----|
      | src |
      (-----|
     -------)

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

    1) link function is called
207 208 209 210
      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
211

212 213 214

                         (- X --------)
                         |            |
215
                         | target *----->//
216 217 218 219 220 221 222 223 224
                        >(------------)
       (real pad link) /      |
                      /      (- Y ------)
                     /    -----* target |
          -------)  /    /   (----------)
                 | /    /                 
           (-----|/    /                  
           | src |<----                    
           (-----|                            
225 226 227 228 229 230 231
          -------)


* Linking a pad to a targetted ghostpad:

    gst_pad_link (src, X)

232 233 234 235 236 237 238 239 240 241 242 243 244 245
                                                 (--------
                         (- X --------)          |
                         |            |          |------)
                         | target *------------->| sink |
                         (------------)         >|------)
                                    |          / (--------
                                    |         /
                                    |        /
          -------)                  |       / (real pad link)
		 |            (- Y ------) /
           (-----|            |          |/
           | src |       //<----* target |
           (-----|            (----------)
          -------)
246 247 248


    1) link function is called
249 250 251 252
      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
253 254

                                                 (--------
255
                         (- X --------)          |
256 257
                         |            |          |------)
                         | target *------------->| sink |
258 259 260
                        >(------------)         >|------)
       (real pad link) /            |          / (--------
                      /             |         /
261
                     /              |        /
262
          -------)  /               |       / (real pad link)
263 264 265 266 267 268 269 270 271 272 273
		 | /          (- Y ------) /
           (-----|/           |          |/
           | src |<-------------* target |
           (-----|            (----------)
          -------)


* Setting target on untargetted linked ghostpad:

   gst_ghost_pad_set_target (char *name, GstPad *newtarget)

274
                                      
275
                         (- X --------)
276 277 278 279 280
                         |            | 
                         | target *------>//
                        >(------------)
       (real pad link) /            |
                      /             |
281
                     /              |
282
          -------)  /               |
283 284 285 286 287 288
		 | /          (- Y ------)
           (-----|/           |          |
           | src |<-------------* target |
           (-----|            (----------)
          -------)

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

293
                                                 (--------
294
                         (- X --------)          |
295 296
                         |            |          |------)
                         | target *------------->| sink |
297 298 299
                        >(------------)         >|------)
       (real pad link) /            |          / (--------
                      /             |         /
300
                     /              |        /
301
          -------)  /               |       / (real pad link)
302 303 304 305 306 307 308 309 310 311 312
		 | /          (- Y ------) /
           (-----|/           |          |/
           | src |<-------------* target |
           (-----|            (----------)
          -------)

* Setting target on targetted linked ghostpad:

   gst_ghost_pad_set_target (char *name, GstPad *newtarget)

                                                 (--------
313
                         (- X --------)          |
314 315 316 317 318
                         |            |          |-------)
                         | target *------------->| sink1 |
                        >(------------)         >|-------)
       (real pad link) /            |          / (--------
                      /             |         /
319
                     /              |        /
320
          -------)  /               |       / (real pad link)
321 322 323 324 325
		 | /          (- Y ------) /
           (-----|/           |          |/
           | src |<-------------* target |
           (-----|            (----------)
          -------)
326

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

332
                                                 (--------
333
                         (- X --------)          |
334 335 336 337 338
                         |            |          |-------)
                         | target *------------->| sink2 |
                        >(------------)         >|-------)
       (real pad link) /            |          / (--------
                      /             |         /
339
                     /              |        /
340
          -------)  /               |       / (real pad link)
341 342 343 344 345 346
		 | /          (- Y ------) /
           (-----|/           |          |/
           | src |<-------------* target |
           (-----|            (----------)
          -------)

347 348

Activation
349
~~~~~~~~~~
350 351 352 353

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

354 355 356 357 358 359 360 361 362 363 364
  +---+     +----+                             +----+       +----+
  | A +-----+ B  |                             | C  |-------+ D  |
  +---+     +---=+                             +=---+       +----+
              +--=-----------------------------=-+
              |  +=---+   +----+  +----+  +---=+ |
              |  | a  +---+ b  ====  c +--+ d  | |
              |  +----+   +----+  +----+  +----+ |
              |                                  |
              +----------------------------------+
              state change goes from right to left
     <-----------------------------------------------------------
365 366 367 368 369 370 371 372 373 374 375 376

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:

377 378 379 380
  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
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

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
Piotr Fusik's avatar
Piotr Fusik committed
409
data flow is already occurring.
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

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
448 449 450 451


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