mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-15 22:01:27 +00:00
Some more docs
Original commit message from CVS: Some more docs
This commit is contained in:
parent
11f8f6a649
commit
faeeed3dba
3 changed files with 382 additions and 0 deletions
63
docs/design/part-negotiation.txt
Normal file
63
docs/design/part-negotiation.txt
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
Negotiation
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Negotiation happens when elements want to push buffers and need to decide
|
||||||
|
on the format.
|
||||||
|
|
||||||
|
For any two linked pads there are different ways to agree on the format but
|
||||||
|
in general the source pad will propose a format and the sink format accepts
|
||||||
|
or rejects.
|
||||||
|
|
||||||
|
src sink
|
||||||
|
| |
|
||||||
|
| accepts? |
|
||||||
|
|---------------->|
|
||||||
|
| yes |
|
||||||
|
|<----------------|
|
||||||
|
| |
|
||||||
|
get buffer | alloc_buf |
|
||||||
|
from pool |---------------->|
|
||||||
|
with type | | Create buffer of type.
|
||||||
|
| |
|
||||||
|
check type |<----------------|
|
||||||
|
and use | |
|
||||||
|
| push |
|
||||||
|
push buffer |---------------->| Receive type, reconfigure to
|
||||||
|
with new type| | process type.
|
||||||
|
| |
|
||||||
|
|
||||||
|
Use case:
|
||||||
|
|
||||||
|
|
||||||
|
videotestsrc ! xvimagesink
|
||||||
|
|
||||||
|
1) Who decides what format to use?
|
||||||
|
- src pad always decides, by convention. sinkpad can suggest a format
|
||||||
|
by putting it high in the getcaps function GstCaps.
|
||||||
|
- since the src decides, it can always choose something that it can do,
|
||||||
|
so this step can only fail if the sinkpad stated it could accept
|
||||||
|
something while it later on couldn't.
|
||||||
|
|
||||||
|
2) When does negotiation happen?
|
||||||
|
- before srcpad does a push, it figures out a type as stated in 1), then
|
||||||
|
it calls the pad alloc function with the type. The sinkpad has to
|
||||||
|
create a buffer of that type, src fills the buffer and sends it to sink.
|
||||||
|
- since the sink stated in 1) it could accept the type, it will be able to
|
||||||
|
create a buffer of the type and handle it.
|
||||||
|
- sink checks media type of buffer and configures itself for this type.
|
||||||
|
|
||||||
|
3) How can sink request another format?
|
||||||
|
- sink asks if new format is possible for the source.
|
||||||
|
- sink returns buffer with new type in allocfunction.
|
||||||
|
- src receives buffer with new type, reconfigures and pushes.
|
||||||
|
- sink can always select something it can create and handle since it takes
|
||||||
|
the initiative. src should be able to handle the new type since it said
|
||||||
|
it could accept it.
|
||||||
|
|
||||||
|
videotestsrc ! queue ! xvimagesink
|
||||||
|
|
||||||
|
- queue implements an allocfunction, proxying all calls to its srcpad peer.
|
||||||
|
- queue proxies all accept and getcaps to the other peer pad.
|
||||||
|
|
||||||
|
|
||||||
|
|
178
docs/design/part-scheduling.txt
Normal file
178
docs/design/part-scheduling.txt
Normal file
|
@ -0,0 +1,178 @@
|
||||||
|
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.
|
||||||
|
|
||||||
|
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)
|
141
docs/design/part-states.txt
Normal file
141
docs/design/part-states.txt
Normal file
|
@ -0,0 +1,141 @@
|
||||||
|
States
|
||||||
|
======
|
||||||
|
|
||||||
|
Both elements an pads can be in different states. The states of the pads are
|
||||||
|
linked to the state of the element so the design of the states is mainly
|
||||||
|
focused around the element states.
|
||||||
|
|
||||||
|
An element can be in 4 states. NULL, READY, PAUSED and PLAYING. When an element
|
||||||
|
is initially instantiated, it is in the NULL state.
|
||||||
|
|
||||||
|
|
||||||
|
State definitions
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
- NULL: This is the initial state of an element.
|
||||||
|
- READY: The element should be prepared to go to PAUSED.
|
||||||
|
- PAUSED: The element should be ready to accept and process data. Sink
|
||||||
|
elements however only accept one sample and then block.
|
||||||
|
- PLAYING: The same as PAUSED except for sinks, who are now accepting
|
||||||
|
and rendering data.
|
||||||
|
|
||||||
|
|
||||||
|
State variables
|
||||||
|
---------------
|
||||||
|
|
||||||
|
An element has a special lock to manage the state changes. This lock is called
|
||||||
|
the STATE_LOCK.
|
||||||
|
|
||||||
|
The STATE_LOCK protects 3 element variables:
|
||||||
|
|
||||||
|
- STATE
|
||||||
|
- PENDING_STATE
|
||||||
|
- STATE_ERROR flag
|
||||||
|
|
||||||
|
The STATE always reflects the current state of the element. The PENDING_STATE
|
||||||
|
always reflects the required state of the element. The PENDING_STATE can be
|
||||||
|
VOID_PENDING if the element is in the right state. The STATE_ERROR flag
|
||||||
|
indicates that an error occured while doing the last state change.
|
||||||
|
|
||||||
|
|
||||||
|
Setting state on elements
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
The state of an element can be changed with _element_set_state(). When chaning
|
||||||
|
the state of an element all intermediate states will also be set on the element
|
||||||
|
until the final desired state is set.
|
||||||
|
|
||||||
|
The _set_state() function can return 3 possible values:
|
||||||
|
|
||||||
|
GST_STATE_FAILURE: The state change failed for some reason. The plugin should
|
||||||
|
have posted an error message on the bus with information.
|
||||||
|
|
||||||
|
GST_STATE_SUCCESS: The state change is completed successfully.
|
||||||
|
|
||||||
|
GST_STATE_ASYNC: The state change will complete later on. This can happen
|
||||||
|
When the element needs a long time to perform the state
|
||||||
|
change or for sinks that need to receive the first sample
|
||||||
|
before they can complete the state change (preroll).
|
||||||
|
|
||||||
|
In the case of an async state change, it is not possible to proceed to the next
|
||||||
|
state until the current state change completed. After receiving an ASYNC return
|
||||||
|
value, you can use _element_get_state() to poll the status of the plugin.
|
||||||
|
|
||||||
|
When setting the state of an element, the PENDING_STATE is set to the required
|
||||||
|
state and the STATE_ERROR flag is cleared. Then the state change function of the
|
||||||
|
element is called and the result of that function is used to update the STATE,
|
||||||
|
PENDING_STATE and STATE_ERROR flags. If the function returned ASYNC, this result
|
||||||
|
is immediatly returned to the caller.
|
||||||
|
|
||||||
|
|
||||||
|
Getting state of elements
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
The _get_state() function takes 3 arguments, two pointers that will hold the
|
||||||
|
current and pending state and one GTimeVal that holds a timeout value. The
|
||||||
|
function returns a GstElementStateReturn.
|
||||||
|
|
||||||
|
- If the element returned SUCCESS to the previous _set_state() function, this
|
||||||
|
function will return the last state set on the element and VOID_PENDING in
|
||||||
|
the pending state value.
|
||||||
|
|
||||||
|
- If the element returned FAILURE to the previous _set_state() call, this
|
||||||
|
funciton will return FAILURE with the state set to the current state of
|
||||||
|
the element and the pending state set to the value used in the last call
|
||||||
|
of _set_state().
|
||||||
|
|
||||||
|
- If the element returned ASYNC to the previous _set_state() call, this function
|
||||||
|
will wait for the element to complete its state change up to the amount of time
|
||||||
|
specified in the GTimeVal.
|
||||||
|
|
||||||
|
* If the element does not complete the state change in the specified amount of
|
||||||
|
time, this function will return ASYNC with the state set to the current state
|
||||||
|
and the pending state set to the pending state.
|
||||||
|
|
||||||
|
* If the element completes the state change within the specified timeout, this
|
||||||
|
function returns the updated state and VOID_PENDING as the pending state.
|
||||||
|
|
||||||
|
* If the element aborts the ASYNC state change due to an error within the
|
||||||
|
specified timeout, this function returns FAILURE with the state set to last
|
||||||
|
successfull state and pending set to the last attempt. The element should
|
||||||
|
also post an error message on the bus with more information about the problem.
|
||||||
|
|
||||||
|
|
||||||
|
States in GstBin
|
||||||
|
----------------
|
||||||
|
|
||||||
|
A GstBin manages the state of its children. It does this by propagating the state
|
||||||
|
changes performed on it to all of its children.
|
||||||
|
|
||||||
|
The _set_state() function on a bin will call the _set_state() function on all of
|
||||||
|
its children. The children are iterated from the sink elements to the source
|
||||||
|
elements.
|
||||||
|
|
||||||
|
If all the children return SUCCESS, the function returns SUCCESS as well.
|
||||||
|
|
||||||
|
If one of the children returns FAILURE, the function returns FAILURE as well. In
|
||||||
|
this state it is possible that some elements successfuly changed state. The
|
||||||
|
application can check which elements have a changed state, which were in error
|
||||||
|
and which were not affected by iterating the elements and calling _get_state()
|
||||||
|
on the elements.
|
||||||
|
|
||||||
|
If after calling the state function on all children, one of the children returned
|
||||||
|
ASYNC, the function returns ASYNC as well.
|
||||||
|
|
||||||
|
The current state of the bin can be retrieved with _get_state(). This function will
|
||||||
|
call the _get_state() function on all the elements. If one of the children returns
|
||||||
|
FAILURE or ASYNC, the bin reports FAILURE or ASYNC respectively. The bin also
|
||||||
|
updates its state variables after polling its children, this means that the state
|
||||||
|
variables of the bin are only updated after calling _get_state() on the bin.
|
||||||
|
|
||||||
|
|
||||||
|
Implementing states in elements
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
READY
|
||||||
|
-----
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue