Most functions returning an object or an object property have
been changed to return its own reference rather than a constant
reference of the one owned by the object itself. The reason for
- this change is primarily threadsafety. This means, effectively,
+ this change is primarily threadsafety. This means effectively
that return values of functions such as
<function>gst_element_get_pad ()</function>,
<function>gst_pad_get_name ()</function> and many more like these
</listitem>
<listitem>
<para>
- Negotiation is asynchronous. This means that negotiation is,
- downstream, done as data comes in and, upstream, as renegotiation
- is required. All details are described in <xref
- linkend="chapter-negotiation"/>.
+ Negotiation is asynchronous. This means that downstream negotiation
+ is done as data comes in and upstream negotiation is done whenever
+ renegotiation is required. All details are described in
+ <xref linkend="chapter-negotiation"/>.
</para>
</listitem>
<listitem>
In 0.9, event handling and buffers are separated once again. This
means that in order to receive events, one no longer has to set the
<classname>GST_FLAG_EVENT_AWARE</classname> flag, but can simply
- set an event handling function on its sinkpad(s), using the function
- <function>gst_pad_set_event_function ()</function>. The
+ set an event handling function on the element's sinkpad(s), using
+ the function <function>gst_pad_set_event_function ()</function>. The
<function>_chain ()</function>-function will only receive buffers.
</para>
</listitem>
()</function>.
</para>
</listitem>
+ <listitem>
+ <para>
+ The semantics of <symbol>GST_STATE_PAUSED</symbol> and
+ <symbol>GST_STATE_PLAYING</symbol> have changed for elements that
+ are not sink elements. Non-sink elements need to be able to accept
+ and process data already in the <symbol>GST_STATE_PAUSED</symbol>
+ state now (ie. when prerolling the pipeline). More details can be
+ found in <xref linkend="chapter-statemanage-states"/>.
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ If your plugin's state change function hasn't been superseded by
+ virtual start() and stop() methods of one of the new base classes,
+ then your plugin's state change functions may need to be changed in
+ order to safely handle concurrent access by multiple threads. Your
+ typical state change function will now first handle upwards state
+ changes, then chain up to the state change function of the parent
+ class (usually GstElementClass in these cases), and only then handle
+ downwards state changes. See the vorbis decoder plugin in
+ gst-plugins-base for an example.
+ </para>
+ <para>
+ The reason for this is that in the case of downwards state changes
+ you don't want to destroy allocated resources while your plugin's
+ chain function (for example) is still accessing those resources in
+ another thread. Whether your chain function might be running or not
+ depends on the state of your plugin's pads, and the state of those
+ pads is closely linked to the state of the element. Pad states are
+ handled in the GstElement class's state change function, including
+ proper locking, that's why it is essential to chain up before
+ destroying allocated resources.
+ </para>
+ <para>
+ As already mentioned above, you should really rewrite your plugin
+ to derive from one of the new base classes though, so you don't have
+ to worry about these things, as the base class will handle it for you.
+ There are no base classes for decoders and encoders yet, so the above
+ paragraphs about state changes definitively apply if your plugin is a
+ decoder or an encoder.
+ </para>
+ </listitem>
</itemizedlist>
</sect1>
</chapter>
<para>
A state describes whether the element instance is initialized, whether it
is ready to transfer data and whether it is currently handling data. There
- are four states defined in &GStreamer;: <symbol>GST_STATE_NULL</symbol>,
- <symbol>GST_STATE_READY</symbol>, <symbol>GST_STATE_PAUSED</symbol>
- and <symbol>GST_STATE_PLAYING</symbol>.
+ are four states defined in &GStreamer;:
</para>
+ <itemizedlist>
+ <listitem>
+ <para>
+ <symbol>GST_STATE_NULL</symbol>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <symbol>GST_STATE_READY</symbol>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <symbol>GST_STATE_PAUSED</symbol>
+ </para>
+ </listitem>
+ <listitem>
+ <para>
+ <symbol>GST_STATE_PLAYING</symbol>
+ </para>
+ </listitem>
+ </itemizedlist>
<para>
- <symbol>GST_STATE_NULL</symbol> (from now on referred to as
- <quote>NULL</quote>) is the default state of an element. In this state, it
+ which will from now on be referred to simply as <quote>NULL</quote>,
+ <quote>READY</quote>, <quote>PAUSED</quote> and <quote>PLAYING</quote>.
+ </para>
+ <para>
+ <symbol>GST_STATE_NULL</symbol> is the default state of an element. In this state, it
has not allocated any runtime resources, it has not loaded any runtime
libraries and it can obviously not handle data.
</para>
<para>
- <symbol>GST_STATE_READY</symbol> (from now on referred to as
- <quote>READY</quote>) is the next state that an element can be in. In the
+ <symbol>GST_STATE_READY</symbol> is the next state that an element can be in. In the
READY state, an element has all default resources (runtime-libraries,
runtime-memory) allocated. However, it has not yet allocated or defined
anything that is stream-specific. When going from NULL to READY state
they should <emphasis>not</emphasis> be allocated in this state.
</para>
<para>
- <symbol>GST_STATE_PAUSED</symbol> (from now on referred to as
- <quote>PAUSED</quote>) is a state in which an element is by all means able
- to handle data; the only 'but' here is that it doesn't actually handle
- any data. When going from the READY state into the PAUSED state
- (<symbol>GST_STATE_READY_TO_PAUSED</symbol>), the element will
- usually not do anything at all: all stream-specific info is generally
- handled in the <function>_link ()</function>, which is called during caps
- negotiation. Exceptions to this rule are, for example, files: these are
- considered stream-specific data (since one file is one stream), and should
- thus be opened in this state change. When going from the PAUSED back to
- READY (<symbol>GST_STATE_PAUSED_TO_READY</symbol>), all
- stream-specific data should be discarded.
+ <symbol>GST_STATE_PAUSED</symbol> is the state in which an element is
+ ready to accept and handle data. For most elements this state is the same
+ as PLAYING. The only exception to this rule are sink elements. Sink
+ elements only accept one single buffer of data and then block. At this
+ point the pipeline is 'prerolled' and ready to render data immediately.
</para>
<para>
- <symbol>GST_STATE_PLAYING</symbol> (from now on referred to as
- <quote>PLAYING</quote>) is the highest state that an element can be in. It
- is similar to PAUSED, except that now, data is actually passing over the
- pipeline. The transition from PAUSED to PLAYING
- (<symbol>GST_STATE_PAUSED_TO_PLAYING</symbol>) should be as small
- as possible and would ideally cause no delay at all. The same goes for the
- reverse transition (<symbol>GST_STATE_PLAYING_TO_PAUSED</symbol>).
+ <symbol>GST_STATE_PLAYING</symbol> is the highest state that an element
+ can be in. For most elements this state is exactly the same as PAUSED,
+ they accept and process events and buffers with data. Only sink elements
+ need to differentiate between PAUSED and PLAYING state. In PLAYING state,
+ sink elements actually render incoming data, e.g. output audio to a sound
+ card or render video pictures to an image sink.
</para>
<sect1 id="section-statemanage-filters">
<title>Managing filter state</title>
<para>
+ If at all possible, your element should derive from one of the new base
+ classes (<xref linkend="chapter-other-base"/>). There are ready-made
+ general purpose base classes for different types of sources, sinks and
+ filter/transformation elements. In addition to those, specialised base
+ classes exist for audio and video elements and others.
+ </para>
+ <para>
+ If you use a base class, you will rarely have to handle state changes
+ yourself. All you have to do is override the base class's start() and
+ stop() virtual functions (might be called differently depending on the
+ base class) and the base class will take care of everything for you.
+ </para>
+ <para>
+ If, however, you do not derive from a ready-made base class, but from
+ GstElement or some other class not built on top of a base class, you
+ will most likely have to implement your own state change function to
+ be notified of state changes. This is definitively necessary if your
+ plugin is a decoder or an encoder, as there are no base classes for
+ decoders or encoders yet.
+ </para>
+ <para>
An element can be notified of state changes through a virtual function
pointer. Inside this function, the element can initialize any sort of
specific data needed by the element, and it can optionally fail to
static GstElementStateReturn
gst_my_filter_change_state (GstElement *element)
{
+ GstElementStateReturn ret = GST_STATE_SUCCESS;
GstMyFilter *filter = GST_MY_FILTER (element);
switch (GST_STATE_TRANSITION (element)) {
if (!gst_my_filter_allocate_memory (filter))
return GST_STATE_FAILURE;
break;
+ default:
+ break;
+ }
+
+ ret = GST_ELEMENT_CLASS (parent_class)->change_state (element);
+
+ switch (GST_STATE_TRANSITION (element)) {
case GST_STATE_READY_TO_NULL:
gst_my_filter_free_memory (filter);
break;
break;
}
- return GST_CALL_PARENT_WITH_DEFAULT (GST_ELEMENT_CLASS,
- change_state, (element), GST_STATE_SUCCESS);
+ return ret;
}
<!-- example-end state.func b -->
<!-- example-begin state.c b --><!--
#include "register.func"
--><!-- example-end state.c b --></programlisting>
+ <para>
+ Note that upwards (NULL=>READY, READY=>PAUSED, PAUSED=>PLAYING) and
+ downwards (PLAYING=>PAUSED, PAUSED=>READY, READY=>NULL) state changes
+ are handled in two separate blocks with the downwards state change
+ handled only after we have chained up to the parent class's state
+ change function. This is necessary in order to safely handle concurrent
+ access by multiple threads.
+ </para>
+ <para>
+ The reason for this is that in the case of downwards state changes
+ you don't want to destroy allocated resources while your plugin's
+ chain function (for example) is still accessing those resources in
+ another thread. Whether your chain function might be running or not
+ depends on the state of your plugin's pads, and the state of those
+ pads is closely linked to the state of the element. Pad states are
+ handled in the GstElement class's state change function, including
+ proper locking, that's why it is essential to chain up before
+ destroying allocated resources.
+ </para>
</sect1>
</chapter>