diff options
author | Wim Taymans <wim.taymans@gmail.com> | 2005-10-08 16:49:15 +0000 |
---|---|---|
committer | Wim Taymans <wim.taymans@gmail.com> | 2005-10-08 16:49:15 +0000 |
commit | 5b4e6c33c80702e09f46c2497c33d1299a8d3453 (patch) | |
tree | 505578d484c461d94bed81caa42487864955a355 /docs/design/part-states.txt | |
parent | bed8c238f084086e4a73ce5325647343d376bfc9 (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.txt | 213 |
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 + + + + + + |