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