2002-08-02 11:23:05 +00:00
|
|
|
STATUS: pushregion/pullregion is gone
|
|
|
|
-------------------------------------
|
|
|
|
|
2001-01-11 09:42:17 +00:00
|
|
|
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.
|