| Since the plan generation only happens as a result of the state mechanism, |
| I'll describe that first. |
| |
| It's supposed to be recursive, such that setting the state on a Bin |
| recursively sets all the children. However, this needs to be rethought |
| somewhat, in light of some recent ideas on the actual definition of some |
| of the states. |
| |
| The mechanism is thus: When you call gst_element_set_state(element,state), |
| it calls the change_state() class method. The basic Element-provided |
| version just sets or unsets the state. A more complex element like the |
| audiosink will switch on the state and do certain things like open or |
| close the sound card on transition to/from various states. The success or |
| failure of these actions can determine whether or not the state gets |
| [un]set as requested. |
| |
| GtkObject signals enter in here, as whenever a state is successfully |
| changed, the STATE_CHANGE signal is fired, which gives higher-level code |
| the ability to do something based on the change. |
| |
| The Bin's change_state function walks through all its children and sets |
| their state. This is where things get interesting, and where things are |
| going to need to be changed. |
| |
| The issue is what the states are and mean. Currently the states are as |
| follows (from gstelement.h): |
| |
| typedef enum { |
| GST_STATE_COMPLETE = (1 << 0), |
| GST_STATE_RUNNING = (1 << 1), |
| GST_STATE_DISCOVERY = (1 << 2), |
| GST_STATE_PREROLL = (1 << 3), |
| |
| GST_STATE_PLAYING = (1 << 4), |
| GST_STATE_PAUSED = (1 << 5), |
| |
| GST_STATE_MAX = (1 << 15), |
| } GstElementState; |
| |
| COMPLETE means all the necesary information is available to run, i.e. the |
| filename for the disksrc, etc. RUNNING means that it's actually doing |
| something, but that's fuzzy. PLAYING means there really is data flowing |
| through the graph, where PAUSED temporary stops the flow. PLAYING && |
| PAUSED is the same idea as !PLAYING, but there are probably going to be |
| many cases where there really is a distinction. |
| |
| DISCOVERY is intended for the autoconnect case, in those instances where |
| the only way to determine the input or output type of some pad is for an |
| element to actually process some data. The idea in that case is that the |
| source element would be responsible for sending the data non-destructively |
| (in the case of a network client, it would have to save it all up, unless |
| it has seek capabilities over the network), and all downstream elements |
| process it in such a way as to not hose their own state. Or rather, when |
| they cease to do discovery, they completely wipe their state as if nothing |
| ever happened. |
| |
| PREROLL is a local state, used for things like sending the first half of |
| an MPEG GOP through the decoder in order to start playback at a frame |
| somewhere in the middle of said GOP. Not sure how that will work, |
| exactly. |
| |
| |
| The issue is that these states aren't layered, and it most certainly isn't |
| the case that a container isn't able to be of a certain state unless all |
| of its children are. I guess I should explain the idea of reconfigurable |
| pipelines: |
| |
| Build an MP3 player, give it the ability to use audio effects plugins. |
| Since you don't want to have to start the stream over again (especially if |
| it's a network stream) every time you change the effect. This means you |
| need to be able to freeze the pipeline in place to change it, without |
| taking too much time. |
| |
| This matters when you consider that certain state changes should render |
| various state bits invalid. In the FROZEN state these won't happen, |
| because the assumption is that they're temporary. |
| |
| If you haven't noticed by now, the state system isn't entirely |
| self-consistent yet. It needs work, and it needs discussion. |