| 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 | |
| ! | |
| : | |