Some more docs

Original commit message from CVS:
Some more docs
This commit is contained in:
Wim Taymans 2005-01-12 18:51:45 +00:00
parent 11f8f6a649
commit faeeed3dba
3 changed files with 382 additions and 0 deletions

View 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.

View 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
View 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
-----