summaryrefslogtreecommitdiff
path: root/docs/design/part-states.txt
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@gmail.com>2005-10-08 16:49:15 +0000
committerWim Taymans <wim.taymans@gmail.com>2005-10-08 16:49:15 +0000
commit5b4e6c33c80702e09f46c2497c33d1299a8d3453 (patch)
tree505578d484c461d94bed81caa42487864955a355 /docs/design/part-states.txt
parentbed8c238f084086e4a73ce5325647343d376bfc9 (diff)
docs/design/: Many doc updates.
Original commit message from CVS: * docs/design/part-TODO.txt: * docs/design/part-clocks.txt: * docs/design/part-events.txt: * docs/design/part-gstbin.txt: * docs/design/part-gstelement.txt: * docs/design/part-gstpipeline.txt: * docs/design/part-live-source.txt: * docs/design/part-messages.txt: * docs/design/part-overview.txt: * docs/design/part-states.txt: Many doc updates.
Diffstat (limited to 'docs/design/part-states.txt')
-rw-r--r--docs/design/part-states.txt213
1 files changed, 181 insertions, 32 deletions
diff --git a/docs/design/part-states.txt b/docs/design/part-states.txt
index 5b736fd231..a3bc7114a5 100644
--- a/docs/design/part-states.txt
+++ b/docs/design/part-states.txt
@@ -23,6 +23,64 @@ We call the sequence NULL->PLAYING an upwards state change and PLAYING->NULL
a downwards state change.
+State transitions
+-----------------
+
+the following state changes are possible:
+
+ NULL -> READY
+ - The element must check if the resources it needs are available.
+ Audiosinks typically try to probe the device.
+
+ READY -> PAUSED
+ - The element opens the device and prepares itself for PLAYING.
+ - the element pads are activated in order to receive data in PAUSED.
+ streaming threads are started.
+ - some elements might need to return ASYNC and complete the state change
+ when they have enough information. It is a requirement for sinks to
+ return ASYNC and complete the state change when they receive the first
+ buffer or EOS event (prerol). Sinks also block the dataflow when in PAUSED.
+ - a pipeline resets the stream time to 0.
+ - live sources return NO_PREROLL and don't generate data.
+
+ PAUSED -> PLAYING
+ - most elements ignore this state change.
+ - The pipeline selects a clock and distributes this to all the children
+ before setting them to PLAYING. This means that it is only alowed to
+ synchronize on the clock in the PLAYING state.
+ - The pipeline uses the clock and the stream time to calculate the base time.
+ The base time is distributed to all children when performing the state
+ change.
+ - sink elements stop blocking on the preroll buffer or event and start
+ rendering the data.
+ - sinks can post the EOS message in the PLAYING state. It is not allowed to
+ post EOS when not in the PLAYING state.
+ - while streaming in PAUSED or PLAYING elements can create and remove
+ dynamic pads.
+ - live sources start generating data and return SUCCESS.
+
+ PLAYING -> PAUSED
+ - most elements ignore this state change.
+ - The pipeline calculates the stream time based on the last selected clock
+ and the base time. It stores this information to continue playback when
+ going back to the PLAYING state.
+ - sinks unblock any clock wait calls.
+ - sinks return ASYNC from this state change and complete the state change
+ when they receive a buffer or an EOS event.
+ - any queued EOS messages are removed since they will be reposted when going
+ back to the PLAYING state.
+ - live sources stop generating data and return NO_PREROLL.
+
+ PAUSED -> READY
+ - sinks unblock any waits in the preroll.
+ - elements unblock any waits on devices
+ - the element pads are deactivated so that streaming becomes impossible and
+ all streaming threads are stopped.
+
+ READY -> NULL
+ - element removes any dynamically created pads
+
+
State variables
---------------
@@ -32,18 +90,17 @@ the STATE_LOCK.
The STATE_LOCK protects 3 element variables:
- STATE
- - PENDING_STATE
- - STATE_ERROR flag
- - NO_PREROLL flag
+ - STATE_NEXT
+ - STATE_PENDING
+ - STATE_RETURN
-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.
-
-The NO_PREROLL flag indicates that the element said it was not able to preroll
-in its last state change. This flag is used in live sources.
+The STATE always reflects the current state of the element.
+The STATE_NEXT reflects the next state the element will go to.
+The STATE_PENDING always reflects the required state of the element.
+The STATE_RETURN reflects the last return value of a state change.
+The STATE_NEXT and STATE_PENDING can be VOID_PENDING if the element is in
+the right state.
Setting state on elements
-------------------------
@@ -68,13 +125,16 @@ The _set_state() function can return 3 possible values:
will not be able to produce data in the PAUSED state.
In the case of an async state change, it is possible to proceed to the next
-state before the current state change completed. After receiving an ASYNC return
-value, you can use _element_get_state() to poll the status of the element.
-
-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
+state before the current state change completed, however, the element will only
+get to this next state before completing the previous ASYNC state change.
+After receiving an ASYNC return value, you can use _element_get_state() to poll
+the status of the element. If the polling returns SUCCESS, the element completed
+the state change to the last requested state with _set_state().
+
+When setting the state of an element, the STATE_PENDING is set to the required
+state. Then the state change function of the element is called and the result of
+that function is used to update the STATE and STATE_RETURN fields, STATE_NEXT,
+STATE_PENDING and STATE_RETURN fields. If the function returned ASYNC, this result
is immediatly returned to the caller.
@@ -143,21 +203,10 @@ ASYNC, the function returns ASYNC as well.
If after calling the state function on all children, one of the children returned
NO_PREROLL, the function returns NO_PREROLL 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.
-
-First the bin will perform a _get_state() on all children with a 0 timeout. This
-is to find any children with an ERROR/NO_PREROLL result value.
+The current state of the bin can be retrieved with _get_state().
-Then the bin performs the _get_state() with the requested timeout. The reason for
-the 2 phases is that when an ERROR or NO_PREROLL result is found, a blocking
-wait on the sinks might never return.
-
-The _get_state() function will be called on the children with the same timout value
-so the function can potentially block timeout*num_children.
-
-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.
+If the bin is performing an ASYNC state change, it will automatically update its
+current state fields when it receives state messages from the children.
Implementing states in elements
@@ -167,6 +216,106 @@ READY
-----
-
+upward state change
+-------------------
+
+Upward state changes always return ASYNC either if the STATE_PENDING is
+reached or not.
+
+Element:
+
+ A -> B => SUCCESS
+ - commit state
+
+ A -> B => ASYNC
+ - no commit state
+ - element commits state ASYNC
+
+ A -> B while ASYNC
+ - update STATE_PENDING state
+ - no commit state
+ - no change_state called on element
+
+Bin:
+
+ A->B: all elements SUCCESS
+ - commit state
+
+ A->B: some elements ASYNC
+ - no commit state
+ - listen for commit messages on bus
+ - for each commit message, poll elements
+ - if no ASYNC elements, commit state, continue state change
+ to STATE_PENDING
+
+downward state change
+----------------------
+
+Downward state changes only return ASYNC if the final state is ASYNC.
+This is to make sure that it's not needed to wait for an element to
+complete the preroll or other ASYNC state changes when one only wants to
+shut down an element.
+
+Element:
+
+ A -> B => SUCCESS
+ - commit state
+
+ A -> B => ASYNC not final state
+ - commit state on behalf of element
+
+ A -> B => ASYNC final state
+ - element will commit ASYNC
+
+Bin:
+
+ A -> B -> SUCCESS
+ - commit state
+
+ A -> B -> ASYNC not final state
+ - commit state on behalf of element, continue state change
+
+ A -> B => ASYNC final state
+ - no commit state
+ - listen for commit messages on bus
+ - for each commit message, poll elements
+ - if no ASYNC elements, commit state
+
+
+Locking overview (element)
+--------------------------
+
+ set_state(element) change_state (element) stream_thread commit_state (element)
+
+ | | | |
+ | | | |
+ STATE_LOCK | | |
+ | | | |
+ |------------------------>| | |
+ | | | |
+ | | | |
+ | | (start_task) | |
+ | | | |
+ | | STREAM_LOCK |
+ | | | |
+ |<------------------------| | |
+ | ASYNC | |
+ STATE_UNLOCK | |
+ | .....sync........ STATE_LOCK |
+ ASYNC |----------------->|
+ | |
+ | |---> post_message(ASYNC)
+ | |---> if (!final) change_state (next)
+ | | else SIGNAL
+ |<-----------------|
+ STATE_UNLOCK
+ |
+ STREAM_UNLOCK
+
+
+
+
+
+