docs/design/: Some docs updates.

Original commit message from CVS:
* docs/design/part-TODO.txt:
* docs/design/part-negotiation.txt:
* docs/design/part-states.txt:
Some docs updates.
This commit is contained in:
Wim Taymans 2005-02-10 14:34:53 +00:00
parent b1d9edff2f
commit 883680f12b
3 changed files with 120 additions and 14 deletions

12
docs/design/part-TODO.txt Normal file
View file

@ -0,0 +1,12 @@
- changing an object's name after construction is not allowed. Checks are performed
when adding objects to parents that no duplicate names are used, changing the name
to a duplicate name after adding it is therefore allowed and voids internal
consistency.
- check for race in _task_pause()/_stop() since the TASK_LOCK is not held by the
calling thread and the STREAM_LOCK not by the task code.
- only emit EOS in PLAYING.
- implement state change order on get<->loop-get<->loop elements.

View file

@ -2,30 +2,116 @@ Negotiation
-----------
Negotiation happens when elements want to push buffers and need to decide
on the format.
on the format. This is called downstream negotiation because the upstream
element decides the format for the downstream element. This is the most
common case.
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.
Negotiation can also happen when a downstream element wants to receive
another data format from an upstream element. This is called upstream
negotiation.
The basics of negotiation are as follows:
- GstCaps (see part-caps.txt) are attached and refcounted before they
are attached to a buffer to describe the contents of the buffer.
It is possible to add a NULL caps to a buffer, this means that the
buffer type did not change relative to the previous buffer.
- Before receiving a buffer, an element must check if the datatype of
the buffer has changed. The element should reconfigure itself to the
new format before processing the buffer data. If the data type on
the buffer is not acceptable, the element should refuse the buffer.
- When requesting a buffer from a bufferpool, the prefered type should
be passed to the buffer allocation function. After receiving a buffer
from a bufferpool, the datatype should be checked again.
- A bufferpool allocation function should try to allocate a buffer of the
prefered type. If there is a good reason to choose another type, the
alloc function should see if that other type is accepted by the other
element, then allocate a buffer of that type and attach the type to the
buffer before returning it.
The general flow for a source pad starting the negotiation.
src sink
| |
| accepts? |
|---------------->|
type A |---------------->|
| yes |
|<----------------|
| |
get buffer | alloc_buf |
from pool |---------------->|
with type | | Create buffer of type.
with type A | | Create buffer of type A.
| |
check type |<----------------|
and use | |
and use A | |
| push |
push buffer |---------------->| Receive type, reconfigure to
with new type| | process type.
push buffer |---------------->| Receive type A, reconfigure to
with new type| | process type A.
| |
One possible implementation in pseudo code:
[element wants to create a buffer]
if not format
# see what the peer can do
peercaps = gst_pad_peer_get_caps (srcpad)
# see what we can do
ourcaps = gst_pad_get_caps (srcpad)
# get common formats
candidates = gst_caps_intersect (peercaps, ourcaps)
foreach candidate in candidates
# make sure the caps is fixed
fixedcaps = gst_pad_fixate_caps (srcpad, candidate)
# see if the peer accepts it
if gst_pad_peer_accept_caps (srcpad, fixedcaps)
# store the caps as the negotiated caps, this will
# call the setcaps function on the pad
gst_pad_set_caps (srcpad, fixedcaps)
break
endif
done
endif
# if the type is different, this will call the setcaps function of
# the pad.
buffer = gst_pad_alloc_buffer (srcpad, 0, size, GST_PAD_CAPS (fixedcaps));
if buffer
[fill buffer and push]
elseif
[no buffer, either no peer or no acceptable format found]
endif
The general flow for a sink pad starting a renegotiation.
src sink
| |
| accepts? |
|<----------------| type B
| yes |
|---------------->|
| |
get buffer | alloc_buf |
from pool |---------------->|
with type | | Create buffer of new type B.
| |
check type |<----------------|
and | |
reconfigure | |
| push |
push buffer |---------------->| Receive type B, reconfigure to
with new type| | process type B.
| |
Use case:
@ -36,7 +122,7 @@ videotestsrc ! xvimagesink
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.
something while later on it couldn't.
2) When does negotiation happen?
- before srcpad does a push, it figures out a type as stated in 1), then
@ -58,6 +144,7 @@ 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.
- queue contains buffers with different types.

View file

@ -19,6 +19,9 @@ State definitions
- PLAYING: The same as PAUSED except for sinks, who are now accepting
and rendering data.
We call the sequence NULL->PLAYING an upwards state change and PLAYING->NULL
a downwards state change.
State variables
---------------
@ -105,11 +108,15 @@ 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.
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 _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.
The children are iterated from the sink elements to the source elements. This makes
sure that when changing the state of an element, the downstream elements are in
the correct state to process the eventual buffers. In the case of a downwards
state change, the sink elements will shut down first which makes the upstream
elements shut down as well since the _push() function returns a GST_FLOW_WRONG_STATE
error.
If all the children return SUCCESS, the function returns SUCCESS as well.