aboutsummaryrefslogtreecommitdiff
path: root/docs/design/part-scheduling.txt
blob: e3fc9ec9db1840a97f9173feb11803e5727f1c45 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
Scheduling
----------

The scheduling in GStreamer is based on pads actively pushing (producing) data or
pad pulling in data (consuming) from other pads.

Pushing
~~~~~~~

A pad can produce data and push it to the next pad. A pad that behaves this way
exposes a loop function that will be called repeatedly until it returns false.
The loop function is allowed to block whenever it wants. When the pad is deactivated
the loop function should unblock though.

A pad operating in the push mode can only produce data to a pad that exposes a
chain function. This chain function will be called with the buffer produced by
the pushing pad. 

This method of producing data is called the streaming mode since the producer 
produces a constant stream of data. 

Pulling
~~~~~~~

Pads that operate in pulling mode can only pull data from a pad that exposes the
pull_range function. In this case, the sink pad exposes a loop function that will be
called repeatedly until the task is stopped.

After pulling data from the peer pad, the loop function will typically call the
push function to push the result to the peer sinkpad.


Deciding the scheduling mode
~~~~~~~~~~~~~~~~~~~~~~~~~~~~

When a pad is activated, the _activate() function is called. The pad can then
choose to activate itself in push or pull mode depending on upstream
capabilities.

The GStreamer core will by default activate pads in push mode when there is no
activate function for the pad.

The chain function
~~~~~~~~~~~~~~~~~~

The chain function will be called when a upstream element performs a _push() on the pad.
The upstream element can be another chain based element or a pushing source.

The getrange function
~~~~~~~~~~~~~~~~~~~~~

The getrange function is called when a peer pad performs a _pull_range() on the pad. This
downstream pad can be a pulling element or another _pull_range() based element.


Scheduling Query
~~~~~~~~~~~~~~~~

A sinkpad can ask the upstream srcpad for its scheduling attributes. It does
this with the SCHEDULING query.


 (out) "pull-mode", G_TYPE_BOOLEAN (default FALSE)
       - if the pad can operate in pull mode, if this flag is not set the pad
         will operate in push mode.

 (out) "random-access", G_TYPE_BOOLEAN (default FALSE)
       - the offset of a pull operation can be specified, if this flag is false,
         the offset should be -1,

 (out) "sequential", G_TYPE_BOOLEAN (default TRUE)
       - suggest sequential access to the data. If random-access is specified,
         seeks are allowed but should be avoided. This is common for network
         streams. (

 (out) "minsize", G_TYPE_INT (default 1)
       - the suggested minimum size of pull requests

 (out) "maxsize", G_TYPE_INT (default -1, unlimited)
       - the suggested maximum size of pull requests

 (out) "align", G_TYPE_INT (default 1)
       - the suggested alignment for the pull requests.



Plug-in techniques
~~~~~~~~~~~~~~~~~~

Multi-sink elements
^^^^^^^^^^^^^^^^^^^

Elements with multiple sinks can either expose a loop function on each of the pads to
actively pull_range data or they can expose a chain function on each pad.

Implementing a chain function is usually easy and allows for all possible scheduling
methods.

Pad select
----------

  If the chain based sink wants to wait for one of the pads to receive a buffer, just
  implement the action to perform in the chain function. Be aware that the action could
  be performed in different threads and possibly simultaneously so grab the STREAM_LOCK.

Collect pads
------------

  If the chain based sink pads all require one buffer before the element can operate on
  the data, collect all the buffers in the chain function and perform the action when
  all chainpads received the buffer.

  In this case you probably also don't want to accept more data on a pad that has a buffer
  queued. This can easily be done with the following code snippet:

    static GstFlowReturn _chain (GstPad *pad, GstBuffer *buffer) 
    {
      LOCK (mylock);
      while (pad->store != NULL) {
        WAIT (mycond, mylock);
      }
      pad->store = buffer;
      SIGNAL (mycond);
      UNLOCK (mylock);

      return GST_FLOW_OK;
    }

    static void _pull (GstPad *pad, GstBuffer **buffer) 
    {
      LOCK (mylock);
      while (pad->store == NULL) {
        WAIT (mycond, mylock);
      }
      **buffer = pad->store;
      pad->store = NULL;
      SIGNAL (mycond);
      UNLOCK (mylock);
    }
  

Cases
~~~~~

Inside the braces below the pads is stated what function the
pad support:

  l: exposes a loop function, so it can act as a pushing source.
  g: exposes a getrange function
  c: exposes a chain function

  following scheduling decisions are made based on the scheduling
  methods exposed by the pads:

  (g) - (l): sinkpad will pull data from src
  (l) - (c): srcpad actively pushes data to sinkpad
  ()  - (c): srcpad will push data to sinkpad.

  ()  - () : not schedulable.
  ()  - (l): not schedulable.
  (g) - () : not schedulable. 
  (g) - (c): not schedulable.
  (l) - () : not schedulable.
  (l) - (l): not schedulable

  ()  - (g): impossible
  (g) - (g): impossible.
  (l) - (g): impossible
  (c) - () : impossible
  (c) - (g): impossible
  (c) - (l): impossible
  (c) - (c): impossible

 +---------+    +------------+    +-----------+
 | filesrc |    | mp3decoder |    | audiosink |
 |        src--sink         src--sink         |
 +---------+    +------------+    +-----------+
         (l-g) (c)           ()   (c)

 When activating the pads:

   * audiosink has a chain function and the peer pad has no
     loop function, no scheduling is done.
   * mp3decoder and filesrc expose an (l) - (c) connection,
     a thread is created to call the srcpad loop function.

 +---------+    +------------+    +----------+
 | filesrc |    | avidemuxer |    | fakesink |
 |        src--sink         src--sink        |
 +---------+    +------------+    +----------+
         (l-g) (l)          ()   (c)
         
   * fakesink has a chain function and the peer pad has no
     loop function, no scheduling is done.
   * avidemuxer and filesrc expose an (g) - (l) connection,
     a thread is created to call the sinkpad loop function.

 +---------+    +----------+    +------------+    +----------+
 | filesrc |    | identity |    | avidemuxer |    | fakesink |
 |        src--sink       src--sink         src--sink        |
 +---------+    +----------+    +------------+    +----------+
         (l-g) (c)        ()   (l)          ()   (c)

   * fakesink has a chain function and the peer pad has no
     loop function, no scheduling is done.
   * avidemuxer and identity expose no schedulable connection so
     this pipeline is not schedulable.

 +---------+    +----------+    +------------+    +----------+
 | filesrc |    | identity |    | avidemuxer |    | fakesink |
 |        src--sink       src--sink         src--sink        |
 +---------+    +----------+    +------------+    +----------+
         (l-g) (c-l)      (g)  (l)          ()   (c)

   * fakesink has a chain function and the peer pad has no
     loop function, no scheduling is done.
   * avidemuxer and identity expose an (g) - (l) connection,
     a thread is created to call the sinkpad loop function.
   * identity knows the srcpad is getrange based and uses the
     thread from avidemux to getrange data from filesrc.

 +---------+    +----------+    +------------+    +----------+
 | filesrc |    | identity |    | oggdemuxer |    | fakesink |
 |        src--sink       src--sink         src--sink        |
 +---------+    +----------+    +------------+    +----------+
         (l-g) (c)        ()   (l-c)        ()   (c)

   * fakesink has a chain function and the peer pad has no
     loop function, no scheduling is done.
   * oggdemuxer and identity expose an () - (l-c) connection,
     oggdemux has to operate in chain mode.
   * identity chan only work chain based and so filesrc creates
     a thread to push data to identity.