| STATUS: pushregion/pullregion is gone |
| ------------------------------------- |
| |
| Changed the way things are scheduled, especially sources. A Src used to |
| have a push() function, and optionally a pushregion() to deal with async |
| reads, etc. That whole thing has gone away, in favor of providing a |
| pull() function for the output (Src) pad instead, ala chain functions. |
| This makes constructing cothreaded schedules out of non-loop elements |
| somewhat easier. Basically there was always a question as to which pad |
| was being dealt with. In the pullregion case, cothread-specific data was |
| used to try to pass the region struct to the right place, which is a slow |
| hack. And in general, the push function severely limited the kind of |
| tricks that could be played when there's more than one output pad, such as |
| a multi-out file reader with async capabilities on each pad independently. |
| |
| This changes the way cothread scheduling occurs. Instead of the hack to |
| deal with Src's by calling their push() function (or optionally the |
| pushregion(), in certain cases), we now are working towards a general |
| mechanism where pads are the only thing that are dealt with directly. |
| |
| An optimization was made in the process of doing this: the loopfunction |
| actually run as the outer [stack] frame of the cothread is now set more |
| intelligently in create_plan() based on what kind of element it is. We |
| now have: |
| |
| loopfunc_wrapper: used for loop-based elements, it simply calls the |
| loopfunc in a loop, paying attention to COTHREAD_STOPPING (see |
| below). It currently does other, soon to be depracated, stuff. |
| |
| pullsrc_wrapper: wraps a Src that's not loop-based (since your options |
| are now loop- or pull-based) |
| |
| There will be a couple more to deal with other cases, such as Connections |
| and chain-based elements. The general idea is that it's a lot more |
| efficient to make the decisions once in create_plan than to keep doing |
| this huge if/else chain in the wrapper. Just choose the right wrapper up |
| front. It'll be most apparent performance-wise in the case of whichever |
| element context is switched to first for each iteration, since the whole |
| wrapper setup is done for every iteration. |
| |
| The tricky part is that there is now a bit of overloading of the function |
| pointers in a pad. The current meanings (possibly to change a bit more |
| soon) are: |
| |
| chainfunc: as always, chainfunc pointer is mirrored between peer pads |
| (this may change, and the chain func may end up in pushfunc) |
| pushfunc: SrcPad: gst_pad_pushfunc_proxy, cothread_switch to peer |
| SinkPad: none (may take over chainfunc, see below) pullfunc: |
| SrcPad: Src or Connection's function to construct buffers |
| SinkPad: gst_pad_pullfunc_proxy, cothread_switch to peer |
| |
| There are a number of issues remaining with the scheduling, not the least |
| of which is the fact that Connections are still dealt with the old way, |
| with _push() functions and such. I'm trying to figure out a way to unify |
| the system so it makes sense. Following the scheduling system is hard |
| enough, trying to change it is murder. |
| |
| |
| Another useful scheduling addition, mentioned above, is COTHREAD_STOPPING. |
| It's an element flag that's used to signal whatever code is running in |
| cothread context that it should be finishing up and exiting soon. An |
| example of this is in plugins/cobin/spindentity.c. All the loops should |
| now be composed of do/while loops, rather than while(1) loops: |
| |
| do { |
| buf = gst_pad_pull(spindentity->sinkpad); |
| gst_pad_push(spindentity->srcpad,buf); |
| } while (!GST_ELEMENT_IS_COTHREAD_STOPPING(element)); |
| |
| The reason for this is that COTHREAD_STOPPING may be set before the above |
| loop ever gets started. It wouldn't do for the body of the loop to never |
| once get called, that would simply stall the pipeline. Note that only the |
| core library code is ever responsible for setting and unsetting this flag. |
| All elements have to do is respond to it by cleanly exiting the loop and |
| the function holding it. |
| |
| This is needed primarily to allow iterations to occur properly. |
| Basically, there's a single entry point in the cothread scheduling loop, |
| gst_bin_iterate_func() simply switches to this cothread. If the element |
| in this context is allowed to loop infinitely, nothing would even switch |
| back to the context from which the iterate() was originally called. This |
| is a bit of a problem. The solution is for there to be an implicit switch |
| back to the originating context. Now, even I'm not sure exactly how this |
| works, but if the cothread that's switched to actually returns, execution |
| returns back to the calling context, i.e. iterate_func(). |
| |
| COTHREAD_STOPPING is therefore set just before switching into this |
| (currently randomly chosen) context, on the assumption that it will return |
| promptly after finishing its duties. The burden of clearing the flag |
| falls to the various wrapper functions provided by the Bin code, thus |
| element writers don't have to worry about doing that at all (and simply |
| shouldn't). |
| |
| |
| Related changes: |
| All the sources in elements/ have been changed to reflect the new system. |
| |
| |
| FIXMEs: |
| 1) gstpipeline.c calls gst_src_push at some point, dunno why, it's |
| commented out now. |
| 2) any other sources, including vcdsrc, dvdsrc, and v4lsrc will break |
| badly and need to be modified to work as pull-based sources. |