2016-12-05 21:12:24 +00:00
|
|
|
# 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
|
2016-12-29 22:43:26 +00:00
|
|
|
exposes the `pull_range()` function. In this case, the sink pad exposes a
|
2016-12-05 21:12:24 +00:00
|
|
|
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
|
|
|
|
|
2016-12-29 22:43:26 +00:00
|
|
|
When a pad is activated, the `_activate()` function is called. The pad
|
2016-12-05 21:12:24 +00:00
|
|
|
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
|
2016-12-29 22:43:26 +00:00
|
|
|
`_push()` on the pad. The upstream element can be another chain based
|
2016-12-05 21:12:24 +00:00
|
|
|
element or a pushing source.
|
|
|
|
|
|
|
|
## The getrange function
|
|
|
|
|
|
|
|
The getrange function is called when a peer pad performs a
|
2016-12-29 22:43:26 +00:00
|
|
|
`_pull_range()` on the pad. This downstream pad can be a pulling element
|
|
|
|
or another `_pull_range()` based element.
|
2016-12-05 21:12:24 +00:00
|
|
|
|
|
|
|
## Scheduling Query
|
|
|
|
|
|
|
|
A sinkpad can ask the upstream srcpad for its scheduling attributes. It
|
2016-12-29 22:43:26 +00:00
|
|
|
does this with the `SCHEDULING` query.
|
2016-12-05 21:12:24 +00:00
|
|
|
|
2016-12-29 22:43:26 +00:00
|
|
|
* (out) **`modes`**: `G_TYPE_ARRAY` (default NULL): an array of `GST_TYPE_PAD_MODE` enums. Contains all the supported scheduling modes.
|
2016-12-05 21:12:24 +00:00
|
|
|
|
2016-12-29 22:43:26 +00:00
|
|
|
* (out) **`flags`**, `GST_TYPE_SCHEDULING_FLAGS` (default 0):
|
2016-12-05 21:12:24 +00:00
|
|
|
|
|
|
|
```c
|
|
|
|
typedef enum {
|
|
|
|
GST_SCHEDULING_FLAG_SEEKABLE = (1 << 0),
|
|
|
|
GST_SCHEDULING_FLAG_SEQUENTIAL = (1 << 1),
|
|
|
|
GST_SCHEDULING_FLAG_BANDWIDTH_LIMITED = (1 << 2)
|
|
|
|
} GstSchedulingFlags;
|
|
|
|
```
|
|
|
|
|
|
|
|
*
|
|
|
|
* **`_SEEKABLE`**: the offset of a pull operation can be specified, if this
|
|
|
|
flag is false, the offset should be -1,
|
|
|
|
|
|
|
|
* **` _SEQUENTIAL`**: suggest sequential access to the data. If`` _SEEKABLE`` is
|
|
|
|
specified, seeks are allowed but should be avoided. This is common for network
|
|
|
|
streams.
|
|
|
|
|
|
|
|
* **`_BANDWIDTH_LIMITED`**: suggest the element supports buffering data for
|
|
|
|
downstream to cope with bandwidth limitations. If this flag is on the
|
|
|
|
downstream element might ask for more data than necessary for normal playback.
|
|
|
|
This use-case is interesting for on-disk buffering scenarios for instance. Seek
|
|
|
|
operations might be slow as well so downstream elements should take this into
|
|
|
|
consideration.
|
|
|
|
|
2016-12-29 22:43:26 +00:00
|
|
|
* (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 0): the suggested alignment for the pull requests.
|
2016-12-05 21:12:24 +00:00
|
|
|
|
|
|
|
## Plug-in techniques
|
|
|
|
|
|
|
|
### Multi-sink elements
|
|
|
|
|
|
|
|
Elements with multiple sinks can either expose a loop function on each
|
2016-12-29 22:43:26 +00:00
|
|
|
of the pads to actively `pull_range` data or they can expose a chain
|
2016-12-05 21:12:24 +00:00
|
|
|
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
|
2016-12-29 22:43:26 +00:00
|
|
|
be performed in different threads and possibly simultaneously so grab the `STREAM_LOCK`.
|
2016-12-05 21:12:24 +00:00
|
|
|
|
|
|
|
# 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:
|
|
|
|
|
|
|
|
``` c
|
|
|
|
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
|
|
|
|
|
|
|
|
```
|
2016-12-29 22:43:26 +00:00
|
|
|
+---------+ +------------+ +-----------+
|
|
|
|
| filesrc | | mp3decoder | | audiosink |
|
|
|
|
| src--sink src--sink |
|
|
|
|
+---------+ +------------+ +-----------+
|
|
|
|
(l-g) (c) () (c)
|
2016-12-05 21:12:24 +00:00
|
|
|
```
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
```
|
2016-12-29 22:43:26 +00:00
|
|
|
+---------+ +------------+ +----------+
|
|
|
|
| filesrc | | avidemuxer | | fakesink |
|
|
|
|
| src--sink src--sink |
|
|
|
|
+---------+ +------------+ +----------+
|
|
|
|
(l-g) (l) () (c)
|
2016-12-05 21:12:24 +00:00
|
|
|
```
|
|
|
|
|
|
|
|
- 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.
|
|
|
|
|
|
|
|
```
|
2016-12-29 22:43:26 +00:00
|
|
|
+---------+ +----------+ +------------+ +----------+
|
|
|
|
| filesrc | | identity | | avidemuxer | | fakesink |
|
|
|
|
| src--sink src--sink src--sink |
|
|
|
|
+---------+ +----------+ +------------+ +----------+
|
|
|
|
(l-g) (c) () (l) () (c)
|
2016-12-05 21:12:24 +00:00
|
|
|
```
|
|
|
|
|
|
|
|
- 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.
|
|
|
|
|
|
|
|
```
|
2016-12-29 22:43:26 +00:00
|
|
|
+---------+ +----------+ +------------+ +----------+
|
|
|
|
| filesrc | | identity | | avidemuxer | | fakesink |
|
|
|
|
| src--sink src--sink src--sink |
|
|
|
|
+---------+ +----------+ +------------+ +----------+
|
|
|
|
(l-g) (c-l) (g) (l) () (c)
|
2016-12-05 21:12:24 +00:00
|
|
|
```
|
|
|
|
|
|
|
|
- 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.
|
|
|
|
|
|
|
|
```
|
2016-12-29 22:43:26 +00:00
|
|
|
+---------+ +----------+ +------------+ +----------+
|
|
|
|
| filesrc | | identity | | oggdemuxer | | fakesink |
|
|
|
|
| src--sink src--sink src--sink |
|
|
|
|
+---------+ +----------+ +------------+ +----------+
|
|
|
|
(l-g) (c) () (l-c) () (c)
|
2016-12-05 21:12:24 +00:00
|
|
|
```
|
|
|
|
|
|
|
|
- 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.
|