[gst-devel] concept of state (was: of bins)

in7y118 at public.uni-hamburg.de in7y118 at public.uni-hamburg.de
Mon Oct 6 06:58:07 CEST 2003

I'm in the mood of writing everything I know and how I think it should work 
about states. Not everything currently works like that, I would call that bugs. 
If you disagree with anything I say, well that's why I post it: Let's discuss.
Someone might even put this into the docs later on, I'm in such a mood.

GStreamer elements know 4 states: GST_STATE_NULL, GST_STATE_READY, 
GST_STATE_PAUSED and GST_STATE_PLAYING. To understand what each of these states 
mean, you must understand what is done when the state changes. State changes 
are handled stepwise inside an element. Each element class has a change_state 
handler that takes care of this.
Let's have a look at the different states and state changes.

This is a "naked" element. A newly created element will be in this state. 
Creation of an element will always succeed given enough memory. In this state 
you can't really do much more but query information about supported media 
types, püroperties or pads.

Here the element is supposed to initalize or finalize everything it needs 
external to GStreamer. Examples for this are input/output elements 
opening/closing their devices or files or the Xvideo output connecting 
to/disconnecting from the X server.

The only difference to GST_STATE_NULL is that you can now query a bit more 
information, because external information is available. The Xvideo output 
luginb will now be able to tell you the formats Xvideo supports. And sound 
outputs will tell you what formats the sound card supports. Note however that 
devices are opened in this state. The sound card will be blocked if an output 
plugin accesses it directly.

Now connections to other elements are (de)initialized. The most notable thing 
going on is caps negotiation. Note that going back to READY resets the stream 
to the beginning as it destroys all inter-element information.

An element in this state is fully initialized but not actively processing 
anything. Everything it needs is completely set up, it may even be in the 
middle of some data crunching, but the active processing is stopped.

This sets up the element itself for data processing. This includes making sure 
the scheduler is aware of scheduling this element and so on.

The element is now actively processing data and may at any time be scheduled by 
the scheduler to output buffers.

Element states can be set by calling gst_element_set_state(). 
gst_element_set_state() is threadsafe (FIXME, it isn't!) and can be used to set 
any possible state. It will take care of making these changes step-by-step. It 
returns one of 3 return values: GST_STATE_SUCCESS indicates that everything 
worked as expected, GST_STATE_LOCKED indicates that no error occured, but the 
element did not change state (examples for this can be found below) and 
GST_STATE_FAILURE indicates an error. In the case of GST_STATE_FAILURE the 
current state of the element is undefined and should be queried using 
gst_elment_get_state() when it is needed.

A special attention should be given to container elements (like bins, threads 
or pipelines). The state of a container element always equals the highest state 
of all contained elements or GST_STATE_NULL if the element contains no children.
If you call gst_element_set_state() on a container, the container will try to 
set all of its children to this state regardless of its own state or the state 
of its children. If one of the children returns GST_STATE_FAILURE, it will then 
abort with GST_STATE_FAILURE, cleanup is then up to the application. If no 
child reports an error, it will return GST_STATE_SUCCESS if its state matches 
the requested state and GST_STATE_LOCKED if not.
Note that this allows some funny incidents:
- Changing an empty container element to any state but GST_STATE_NULL will 
always make that bin return GST_STATE_LOCKED.
- Changing a bin in GST_STATE_PLAYING to the same state might result in 
GST_STATE_FAILURE even though the bin's state did not change. This will happen 
when a child element, that previously was not in this state failed to change 
the state.

Another possibility is locking the state of elements. You can use the function 
gst_element_set_locked_state() to lock or unlock elements. Locked elements will 
not change state when calling gstt_element_set_state() on them. Instead they 
will keep their state and always return GST_STATE_LOCKED, even when you want to 
set their state to the state they currently are in.

Makes sense?

Quoting Thomas Vander Stichele <thomas at apestaart.org>:

> What do you think ?

More information about the gstreamer-devel mailing list