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