mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-03-30 12:49:40 +00:00
docs/pwg/: Add some paragraphs about state changes in 0.9 to the PWG and the porting guide, in particular about the n...
Original commit message from CVS: * docs/pwg/appendix-porting.xml: * docs/pwg/building-state.xml: Add some paragraphs about state changes in 0.9 to the PWG and the porting guide, in particular about the new meaning of GST_STATE_PAUSED and how to write state change functions with concurrent access by multiple threads in mind.
This commit is contained in:
parent
cdd579efc9
commit
f40be99d4b
3 changed files with 147 additions and 35 deletions
|
@ -1,3 +1,12 @@
|
|||
2005-08-12 Tim-Philipp Müller <tim at centricular dot net>
|
||||
|
||||
* docs/pwg/appendix-porting.xml:
|
||||
* docs/pwg/building-state.xml:
|
||||
Add some paragraphs about state changes in 0.9 to the PWG
|
||||
and the porting guide, in particular about the new meaning
|
||||
of GST_STATE_PAUSED and how to write state change functions
|
||||
with concurrent access by multiple threads in mind.
|
||||
|
||||
2005-08-11 Stefan Kost <ensonic@users.sf.net>
|
||||
|
||||
* docs/gst/gstreamer-docs.sgml:
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
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
|
||||
|
@ -51,10 +51,10 @@
|
|||
</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>
|
||||
|
@ -73,8 +73,8 @@
|
|||
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>
|
||||
|
@ -99,6 +99,48 @@
|
|||
()</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>
|
||||
|
|
|
@ -3,19 +3,41 @@
|
|||
<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>
|
||||
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> (from now on referred to as
|
||||
<quote>NULL</quote>) is the default state of an element. In this state, it
|
||||
<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
|
||||
|
@ -29,31 +51,44 @@
|
|||
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
|
||||
|
@ -96,6 +131,7 @@ gst_my_filter_free_memory (GstMyFilter * filter)
|
|||
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)) {
|
||||
|
@ -103,6 +139,13 @@ gst_my_filter_change_state (GstElement *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;
|
||||
|
@ -110,12 +153,30 @@ gst_my_filter_change_state (GstElement *element)
|
|||
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>
|
||||
|
|
Loading…
Reference in a new issue