| 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 repeadedly 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 |
| pullregion function. In this case, the sink pad exposes a loop function that will be |
| called repeadedly 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 the core performs the pad activate function, it will select a scheduling mode |
| for the pads. Sinkpads that expose a loop function are prefered over source pads |
| with a loop function so that the pull mode is selected when possible. Selecting the |
| pull mode is more efficient because it allows for arbitrary seeking and random access |
| to the data. |
| |
| The chain function |
| ------------------ |
| |
| The chain function will be called when a upstream element perform 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 perform a _pullregion() on the pad. This |
| downstream pad can be a pulling element or another pullregion() based element. |
| |
| Plug-in techniques |
| ------------------ |
| |
| Multi-sink elements |
| ------------------- |
| |
| Elements with multiple sinks can either expose a loop function on each of the pads to |
| actively pullregion 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. |
| |
| |