3e1734095fdb426ffdf449a74f5183d1bad0fee3
[platform/upstream/gstreamer.git] / docs / design / part-scheduling.txt
1 Scheduling
2 ----------
3
4 The scheduling in GStreamer is based on pads actively pushing (producing) data or
5 pad pulling in data (consuming) from other pads.
6
7 Pushing
8 ~~~~~~~
9
10 A pad can produce data and push it to the next pad. A pad that behaves this way
11 exposes a loop function that will be called repeadedly until it returns false. 
12 The loop function is allowed to block whenever it wants. When the pad is deactivated
13 the loop function should unblock though.
14
15 A pad operating in the push mode can only produce data to a pad that exposes a
16 chain function. This chain function will be called with the buffer produced by
17 the pushing pad. 
18
19 This method of producing data is called the streaming mode since the producer 
20 produces a constant stream of data. 
21
22 Pulling
23 ~~~~~~~
24
25 Pads that operate in pulling mode can only pull data from a pad that exposes the
26 pull_range function. In this case, the sink pad exposes a loop function that will be
27 called repeadedly until the task is stopped.
28
29 After pulling data from the peer pad, the loop function will typically call the
30 push function to push the result to the peer sinkpad.
31
32
33 Deciding the scheduling mode
34 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
35
36 When a pad is activated, the _activate() function is called. The pad can then
37 choose to activate itself in push or pull mode depending on upstream
38 capabilities.
39
40 The GStreamer core will by default activate pads in push mode when there is no
41 activate function for the pad.
42
43 The chain function
44 ~~~~~~~~~~~~~~~~~~
45
46 The chain function will be called when a upstream element performs a _push() on the pad.
47 The upstream element can be another chain based element or a pushing source.
48
49 The getrange function
50 ~~~~~~~~~~~~~~~~~~~~~
51
52 The getrange function is called when a peer pad performs a _pull_range() on the pad. This
53 downstream pad can be a pulling element or another _pull_range() based element.
54
55 Plug-in techniques
56 ~~~~~~~~~~~~~~~~~~
57
58 Multi-sink elements
59 ^^^^^^^^^^^^^^^^^^^
60
61 Elements with multiple sinks can either expose a loop function on each of the pads to
62 actively pull_range data or they can expose a chain function on each pad.
63
64 Implementing a chain function is usually easy and allows for all possible scheduling
65 methods.
66
67 Pad select
68 ----------
69
70   If the chain based sink wants to wait for one of the pads to receive a buffer, just
71   implement the action to perform in the chain function. Be aware that the action could
72   be performed in different threads and possibly simultaneously so grab the STREAM_LOCK.
73
74 Collect pads
75 ------------
76
77   If the chain based sink pads all require one buffer before the element can operate on
78   the data, collect all the buffers in the chain function and perform the action when
79   all chainpads received the buffer.
80
81   In this case you probably also don't want to accept more data on a pad that has a buffer
82   queued. This can easily be done with the following code snippet:
83
84     static GstFlowReturn _chain (GstPad *pad, GstBuffer *buffer) 
85     {
86       LOCK (mylock);
87       while (pad->store != NULL) {
88         WAIT (mycond, mylock);
89       }
90       pad->store = buffer;
91       SIGNAL (mycond);
92       UNLOCK (mylock);
93
94       return GST_FLOW_OK;
95     }
96
97     static void _pull (GstPad *pad, GstBuffer **buffer) 
98     {
99       LOCK (mylock);
100       while (pad->store == NULL) {
101         WAIT (mycond, mylock);
102       }
103       **buffer = pad->store;
104       pad->store = NULL;
105       SIGNAL (mycond);
106       UNLOCK (mylock);
107     }
108   
109
110 Cases
111 ~~~~~
112
113 Inside the braces below the pads is stated what function the
114 pad support:
115
116   l: exposes a loop function, so it can act as a pushing source.
117   g: exposes a getrange function
118   c: exposes a chain function
119
120   following scheduling decisions are made based on the scheduling
121   methods exposed by the pads:
122
123   (g) - (l): sinkpad will pull data from src
124   (l) - (c): srcpad actively pushes data to sinkpad
125   ()  - (c): srcpad will push data to sinkpad.
126
127   ()  - () : not schedulable.
128   ()  - (l): not schedulable.
129   (g) - () : not schedulable. 
130   (g) - (c): not schedulable.
131   (l) - () : not schedulable.
132   (l) - (l): not schedulable
133
134   ()  - (g): impossible
135   (g) - (g): impossible.
136   (l) - (g): impossible
137   (c) - () : impossible
138   (c) - (g): impossible
139   (c) - (l): impossible
140   (c) - (c): impossible
141
142  +---------+    +------------+    +-----------+
143  | filesrc |    | mp3decoder |    | audiosink |
144  |        src--sink         src--sink         |
145  +---------+    +------------+    +-----------+
146          (l-g) (c)           ()   (c)
147
148  When activating the pads:
149
150    * audiosink has a chain function and the peer pad has no
151      loop function, no scheduling is done.
152    * mp3decoder and filesrc expose an (l) - (c) connection,
153      a thread is created to call the srcpad loop function.
154
155  +---------+    +------------+    +----------+
156  | filesrc |    | avidemuxer |    | fakesink |
157  |        src--sink         src--sink        |
158  +---------+    +------------+    +----------+
159          (l-g) (l)          ()   (c)
160          
161    * fakesink has a chain function and the peer pad has no
162      loop function, no scheduling is done.
163    * avidemuxer and filesrc expose an (g) - (l) connection,
164      a thread is created to call the sinkpad loop function.
165
166  +---------+    +----------+    +------------+    +----------+
167  | filesrc |    | identity |    | avidemuxer |    | fakesink |
168  |        src--sink       src--sink         src--sink        |
169  +---------+    +----------+    +------------+    +----------+
170          (l-g) (c)        ()   (l)          ()   (c)
171
172    * fakesink has a chain function and the peer pad has no
173      loop function, no scheduling is done.
174    * avidemuxer and identity expose no schedulable connection so
175      this pipeline is not schedulable.
176
177  +---------+    +----------+    +------------+    +----------+
178  | filesrc |    | identity |    | avidemuxer |    | fakesink |
179  |        src--sink       src--sink         src--sink        |
180  +---------+    +----------+    +------------+    +----------+
181          (l-g) (c-l)      (g)  (l)          ()   (c)
182
183    * fakesink has a chain function and the peer pad has no
184      loop function, no scheduling is done.
185    * avidemuxer and identity expose an (g) - (l) connection,
186      a thread is created to call the sinkpad loop function.
187    * identity knows the srcpad is getrange based and uses the
188      thread from avidemux to getrange data from filesrc.
189
190  +---------+    +----------+    +------------+    +----------+
191  | filesrc |    | identity |    | oggdemuxer |    | fakesink |
192  |        src--sink       src--sink         src--sink        |
193  +---------+    +----------+    +------------+    +----------+
194          (l-g) (c)        ()   (l-c)        ()   (c)
195
196    * fakesink has a chain function and the peer pad has no
197      loop function, no scheduling is done.
198    * oggdemuxer and identity expose an () - (l-c) connection,
199      oggdemux has to operate in chain mode.
200    * identity chan only work chain based and so filesrc creates
201      a thread to push data to identity.
202
203