| There are a number of different ways of coding a GstSrc. I'll try to |
| outline them and how the function here: |
| |
| 1a) Simple push-function based with single output |
| |
| |
| *------* *------ |
| ! ! ! |
| ! src !--->--! plugin |
| ! ! ! |
| *------* *------ |
| |
| This is the style that all the existing sources use. There is a single |
| output pad, and a _push function that's global to the whole element. The |
| _push function simply constructs buffers and pushes them out the pad. |
| |
| Chained (current implementation): |
| |
| |
| bin src pad1 pad2 plugin |
| ! (= pad1->peer) |
| gst_bin_iterate |
| ! |
| ! (find entry) |
| ! |
| ! gst_src_push |
| !---------------->! |
| ! (create buffer) |
| ! |
| ! gst_pad_push |
| !---------------->! |
| ! |
| ! pad1->chainfunc (pad1->peer) |
| !------------------------------->! |
| ! ! |
| : : |
| (more chaining) |
| : : |
| !<-------------------------------! |
| !<----------------! |
| !<-----------------! |
| ! |
| iteration ends |
| ! |
| --- |
| - |
| |
| Typically this will be the/an entry into the Bin. The Bin's iterate |
| function simply calls the Src's _push function. When the _push function |
| pushes a buffer out it's pad, the chain function of the peer pad is |
| called, presumably causing a push out the other side of that element, and |
| eventually data gets to the other end. The stack unrolls, and the |
| iteration ends for that Src. |
| |
| |
| |
| Cothreaded: |
| |
| Again, the source would generally be an entry into the Bin. A loopfunc |
| will be constructed around it, which will simply loop calling the Src's |
| _push function as in the non-cothreaded case. When the _push function |
| pushes a buffer, it finds a pushfunc attached to the pad, drops the buffer |
| in the pen, and calls the pushfunc provided by the Bin. This causes a |
| switch to the next element, then the next, to the end, at which point a |
| buffer pull will travel back down the chain. The _push function gets |
| context and finishes, at which point the loopfunc wrapper simply calls it |
| again in the next iteration. |
| |
| (current implementation): |
| |
| |
| bin cothread1 src pad1 pad2 cothread2 plugin |
| ! (src) (= pad2->peer) (plugin) |
| gst_bin_iterate |
| ! |
| ! (first entry) |
| ! |
| ! cothread_switch |
| !---------------->! |
| ! gst_src_push |
| !---------------->! |
| ! (create buffer) |
| ! |
| ! gst_pad_push (pad1) |
| ! |
| !--------------------! |
| ! (fill bufpen) |
| ! |
| ! cothread switch |
| ----------------------->! |
| ! gst_pad_pull (pad2) |
| ! |
| !<----------! |
| ! |
| ! (get buffer from bufpen) |
| ! |
| !---------->! |
| ! pad2->chainfunc |
| !------------->! |
| ! |
| : |
| |
| : |
| !<-------------! |
| ! gst_pad_pull (pad2) |
| !<----------! |
| ! |
| ! (bufpen empty) |
| !<----------! |
| !<-------------------------------------! cothread switch |
| !<----------------! |
| ! |
| iteration ends |
| ! |
| : |
| |
| : |
| ! |
| next iteration |
| ! |
| ! cothread_switch |
| !---------------->! |
| ! gst_src_push |
| !---------------->! |
| ! (create buffer) |
| ! |
| ! gst_pad_push (pad1) |
| ! |
| !--------------------! |
| ! (fill bufpen) |
| ! |
| ! cothread switch |
| !---------->! |
| ! (get buffer from bufpen) |
| ! |
| !---------->! |
| ! pad2->chainfunc |
| !------------->! |
| ! |
| : |
| |
| : |
| !<-------------! |
| ! gst_pad_pull (pad2) |
| !<----------! |
| ! |
| ! (bufpen empty) |
| !<----------! |
| !<-------------------------------------! cothread switch |
| !<----------------! |
| ! |
| iteration ends |
| ! |
| : |
| |
| |
| ----------------------------------------------------------------------------------------------- |
| 1b) Simple push-function based with multiple output |
| |
| Chained: |
| |
| Similar to the single output variant, except several chains are spawned |
| off, one per push, hanging off whichever pad the buffer is pushed off of. |
| The stack will grow and unwind as many times as buffers are pushed out. |
| |
| (current implementation) |
| |
| bin src pad1 pad2 plugin |
| ! (= pad1->peer) |
| gst_bin_iterate |
| ! |
| ! (find entry) |
| ! |
| ! gst_src_push |
| !---------------->! |
| ! (create buffer) |
| ! |
| ! gst_pad_push |
| !---------------->! |
| ! |
| ! pad1->chainfunc (pad1->peer) |
| !------------------------------->! |
| ! ! |
| : : |
| (more chaining) |
| : : |
| !<-------------------------------! |
| !<----------------! |
| ! (create buffer) |
| ! |
| ! gst_pad_push |
| !---------------->! |
| ! |
| ! pad1->chainfunc (pad1->peer) |
| !------------------------------->! |
| ! ! |
| : : |
| (more chaining) |
| : : |
| !<-------------------------------! |
| !<----------------! |
| : |
| (more pushes) |
| : |
| !<-----------------! |
| ! |
| iteration ends |
| ! |
| --- |
| - |
| |
| |
| Cothreaded: |
| |
| Also similar to the single output variant. When the pull winds its way |
| back from the first push, execution returns to the Src's _push function, |
| which simply goes off and pushes out another buffer, causing another |
| series of context switches. Eventually the loopfunc wrapper starts over, |
| round and round we go. |
| |
| |
| |
| ----------------------------------------------------------------------------------------------- |
| 2) Pull-function based with single output |
| |
| Similar to a regular filter with a chain function associated with each |
| pad, this kind of source doesn't provide a src-wide push function, but |
| does provide pullfuncs for its pad. A pullfunc puts a buffer in the pen |
| and exits. |
| |
| Chained: |
| |
| bin src pad1 pad2 plugin |
| ! (= pad1->peer) |
| gst_bin_iterate |
| ! |
| ! (find entry) |
| ! |
| ! (find src pad |
| ! of entry element) |
| ! |
| ! gst_pad_pull |
| !------------------------------------------------>! |
| ? ! |
| !<------------------------------! |
| ! |
| ! (create buffer) |
| ! |
| ! gst_pad_push |
| !------------------------------>! |
| ! (bufpen filled) |
| (return buffer) ! |
| !<------------------------------------------------! |
| ! |
| ! gst_pad_chain |
| !------------------------------------------------------------------->! |
| ! |
| : |
| (more chaining) |
| : |
| !<-------------------------------------------------------------------! |
| ! |
| iteration ends |
| ! |
| --- |
| - |
| |
| As usual, is likely to be an entry into a Bin. The Bin iterate code must |
| explicitly pull a buffer and pass it on to the peer. |
| |
| Cothreaded: |
| |
| |
| bin cothread1 src pad1 pad2 cothread2 plugin |
| ! (src) (= pad2->peer) (plugin) |
| gst_bin_iterate |
| ! |
| ! (first entry) |
| ! |
| ! cothread_switch |
| !---------------->! gst_pad_pull |
| !------------------------------------------------>! |
| ? ! |
| !<------------------------------! |
| ! |
| ! (create buffer) |
| ! |
| ! gst_pad_push |
| !------------------------------>! |
| ! (bufpen filled) |
| (return buffer) ! |
| !<------------------------------------------------! |
| ! |
| ! pad_chain |
| !--------------------------------------! cothread switch |
| |---------------------->! |
| ! gst_pad_pull (pad2) |
| ! |
| !<----------! |
| ! |
| ! (get buffer from bufpen) |
| ! |
| !---------->! |
| ! pad2->chainfunc |
| !------------->! |
| ! |
| : |
| |
| : |
| !<-------------! |
| ! gst_pad_pull (pad2) |
| !<----------! |
| ! |
| ! (bufpen empty) |
| !<-----------! |
| ! cothread switch |
| !-------------------! |
| !<----------------! |
| !<----------------! |
| ! |
| iteration ends |
| ! |
| : |
| |