f07ccefbbc4f2548a88d37dac7c569d85ec8bd8c
[platform/upstream/gstreamer.git] / docs / pwg / building-state.xml
1 <chapter id="chapter-statemanage-states">
2   <title>What are states?</title>
3   <para>
4     A state describes whether the element instance is initialized, whether it
5     is ready to transfer data and whether it is currently handling data. There
6     are four states defined in &GStreamer;:
7   </para>
8   <itemizedlist>
9     <listitem>
10       <para>
11         <symbol>GST_STATE_NULL</symbol>
12       </para>
13     </listitem>
14     <listitem>
15       <para>
16         <symbol>GST_STATE_READY</symbol>
17       </para>
18     </listitem>
19     <listitem>
20       <para>
21         <symbol>GST_STATE_PAUSED</symbol>
22       </para>
23     </listitem>
24     <listitem>
25       <para>
26         <symbol>GST_STATE_PLAYING</symbol>
27       </para>
28     </listitem>
29   </itemizedlist>
30   <para>
31     which will from now on be referred to simply as <quote>NULL</quote>,
32     <quote>READY</quote>, <quote>PAUSED</quote> and <quote>PLAYING</quote>.
33   </para>
34   <para>
35     <symbol>GST_STATE_NULL</symbol> is the default state of an element. In this state, it
36     has not allocated any runtime resources, it has not loaded any runtime
37     libraries and it can obviously not handle data.
38   </para>
39   <para>
40     <symbol>GST_STATE_READY</symbol> is the next state that an element can be in. In the
41     READY state, an element has all default resources (runtime-libraries,
42     runtime-memory) allocated. However, it has not yet allocated or defined
43     anything that is stream-specific. When going from NULL to READY state
44     (<symbol>GST_STATE_CHANGE_NULL_TO_READY</symbol>), an element should
45     allocate any non-stream-specific resources and should load runtime-loadable
46     libraries (if any). When going the other way around (from READY to NULL,
47     <symbol>GST_STATE_CHANGE_READY_TO_NULL</symbol>), an element should unload
48     these libraries and free all allocated resources. Examples of such
49     resources are hardware devices. Note that files are generally streams,
50     and these should thus be considered as stream-specific resources; therefore,
51     they should <emphasis>not</emphasis> be allocated in this state.
52   </para>
53   <para>
54     <symbol>GST_STATE_PAUSED</symbol> is the state in which an element is 
55     ready to accept and handle data. For most elements this state is the same
56     as PLAYING. The only exception to this rule are sink elements. Sink
57     elements only accept one single buffer of data and then block. At this
58     point the pipeline is 'prerolled' and ready to render data immediately.
59   </para>
60   <para>
61     <symbol>GST_STATE_PLAYING</symbol> is the highest state that an element
62     can be in. For most elements this state is exactly the same as PAUSED,
63     they accept and process events and buffers with data. Only sink elements
64     need to differentiate between PAUSED and PLAYING state. In PLAYING state,
65     sink elements actually render incoming data, e.g. output audio to a sound
66     card or render video pictures to an image sink.
67   </para>
68
69   <sect1 id="section-statemanage-filters">
70   <title>Managing filter state</title>
71   <para>
72     If at all possible, your element should derive from one of the new base 
73     classes (<xref linkend="chapter-other-base"/>). There are ready-made 
74     general purpose base classes for different types of sources, sinks and
75     filter/transformation elements. In addition to those, specialised base 
76     classes exist for audio and video elements and others.
77   </para>
78   <para>
79     If you use a base class, you will rarely have to handle state changes 
80     yourself. All you have to do is override the base class's start() and
81     stop() virtual functions (might be called differently depending on the
82     base class) and the base class will take care of everything for you.
83   </para>
84   <para>
85     If, however, you do not derive from a ready-made base class, but from 
86     GstElement or some other class not built on top of a base class, you 
87     will most likely have to implement your own state change function to
88     be notified of state changes. This is definitively necessary if your
89     plugin is a demuxer or a muxer, as there are no base classes for
90     muxers or demuxers yet.
91   </para>
92   <para>
93     An element can be notified of state changes through a virtual function
94     pointer. Inside this function, the element can initialize any sort of
95     specific data needed by the element, and it can optionally fail to
96     go from one state to another.
97   </para>
98   <para>
99     Do not g_assert for unhandled state changes; this is taken care of by
100     the GstElement base class.
101   </para>
102   <programlisting>
103 static GstStateChangeReturn
104 gst_my_filter_change_state (GstElement *element, GstStateChange transition);
105
106 static void
107 gst_my_filter_class_init (GstMyFilterClass *klass)
108 {
109   GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
110
111   element_class->change_state = gst_my_filter_change_state;
112 }
113 <!-- example-begin state.c a --><!--
114 #include "init.func"
115 #include "caps.func"
116 #include "chain.func"
117 #include "state.func"
118 --><!-- example-end state.c a -->
119 <!-- example-begin state.func a --><!--
120 static gboolean
121 gst_my_filter_allocate_memory (GstMyFilter * filter)
122 {
123   return TRUE;
124 }
125 static void
126 gst_my_filter_free_memory (GstMyFilter * filter)
127 {
128 }
129 --><!-- example-end state.func a -->
130 <!-- example-begin state.func b -->
131 static GstStateChangeReturn
132 gst_my_filter_change_state (GstElement *element, GstStateChange transition)
133 {
134   GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
135   GstMyFilter *filter = GST_MY_FILTER (element);
136
137   switch (transition) {
138     case GST_STATE_CHANGE_NULL_TO_READY:
139       if (!gst_my_filter_allocate_memory (filter))
140         return GST_STATE_CHANGE_FAILURE;
141       break;
142     default:
143       break;
144   }
145
146   ret = GST_ELEMENT_CLASS (parent_class)-&gt;change_state (element, transition);
147   if (ret == GST_STATE_CHANGE_FAILURE)
148     return ret;
149
150   switch (transition) {
151     case GST_STATE_CHANGE_READY_TO_NULL:
152       gst_my_filter_free_memory (filter);
153       break;
154     default:
155       break;
156   }
157
158   return ret;
159 }
160 <!-- example-end state.func b -->
161 <!-- example-begin state.c b --><!--
162 #include "register.func"
163   --><!-- example-end state.c b --></programlisting>
164   <para>
165     Note that upwards (NULL=&gt;READY, READY=&gt;PAUSED, PAUSED=&gt;PLAYING)
166     and downwards (PLAYING=&gt;PAUSED, PAUSED=&gt;READY, READY=&gt;NULL) state
167     changes are handled in two separate blocks with the downwards state change
168     handled only after we have chained up to the parent class's state
169     change function. This is necessary in order to safely handle concurrent
170     access by multiple threads.
171   </para>
172   <para>
173     The reason for this is that in the case of downwards state changes
174     you don't want to destroy allocated resources while your plugin's 
175     chain function (for example) is still accessing those resources in
176     another thread. Whether your chain function might be running or not
177     depends on the state of your plugin's pads, and the state of those
178     pads is closely linked to the state of the element. Pad states are
179     handled in the GstElement class's state change function, including
180     proper locking, that's why it is essential to chain up before
181     destroying allocated resources.
182   </para>
183   </sect1>
184 </chapter>