View Source Membrane.Element.Action (Membrane Core v1.0.1)
This module contains type specifications of actions that can be returned from element callbacks.
Returning actions is a way of element interaction with other elements and parts of framework. Each action may be returned by any callback unless explicitly stated otherwise.
Summary
Types
Sends buffers through a pad.
Action that can be always returned from each of the callbacks.
Makes a demand on a pad.
Marks that processing via a pad (output) has been finished and the pad instance won't be used anymore.
Sends an event through a pad (input or output).
Sends buffers/stream format/event/end of stream to all output pads of element (or to input pads when event occurs on the output pad).
This action sets the latency for the element.
Sends a message to the parent.
Pauses auto-demanding on the specific pad.
Executes Membrane.Element.WithOutputPads.handle_demand/5
callback
for the given pad (or pads), that have demand greater than 0.
Resumes auto-demanding on the specific pad.
Action that manages the end of the component setup.
Allows to split callback execution into multiple applications of another callback (called from now sub-callback).
Starts a timer that will invoke Membrane.Element.Base.handle_tick/3
callback
every interval
according to the given clock
.
Stops a timer started with start_timer/0
action.
Actions that can be returned from callbacks when the element is in playback: :playing
state.
Sends stream format through a pad.
Type that defines a union of actions that may be returned from most of the callbacks.
Terminates element with given reason.
Changes interval of a timer started with start_timer/0
.
Types
@type buffer() :: {:buffer, {Membrane.Pad.ref(), Membrane.Buffer.t() | [Membrane.Buffer.t()]}}
Sends buffers through a pad.
The pad must have output direction.
Allowed only when playback is playing.
@type common_actions() :: notify_parent() | start_timer() | timer_interval() | stop_timer() | terminate() | split()
Action that can be always returned from each of the callbacks.
@type demand() :: {:demand, {Membrane.Pad.ref(), demand_size()}}
Makes a demand on a pad.
The pad must have input direction and work in :manual
flow control mode. This action does NOT
entail sending demand through the pad, but just requesting some amount
of data from pad's internal queue, which sends demands automatically when it
runs out of data.
If there is any data available at the pad, the data is passed to
c:Membrane.WithInputPads.handle_buffer/4
callback. Invoked callback is
guaranteed not to receive more data than demanded.
Demand size can be either a non-negative integer, that overrides existing demand, or a function that is passed current demand, and is to return the new demand.
Allowed only when playback is playing.
@type demand_size() :: pos_integer() | (pos_integer() -> non_neg_integer())
@type end_of_stream() :: {:end_of_stream, Membrane.Pad.ref()}
Marks that processing via a pad (output) has been finished and the pad instance won't be used anymore.
Triggers end_of_stream/3
callback at the receiver element.
Allowed only when playback is in playing state.
@type event() :: {:event, {Membrane.Pad.ref(), Membrane.Event.t()}}
Sends an event through a pad (input or output).
Allowed only when playback is playing
.
@type forward() :: {:forward, Membrane.Buffer.t() | [Membrane.Buffer.t()] | Membrane.StreamFormat.t() | Membrane.Event.t() | :end_of_stream}
Sends buffers/stream format/event/end of stream to all output pads of element (or to input pads when event occurs on the output pad).
Used by default implementations of
Membrane.Element.WithInputPads.handle_stream_format/4
,
Membrane.Element.Base.handle_event/4
and
Membrane.Element.WithInputPads.handle_end_of_stream/3
callbacks in filter.
Allowed only when all below conditions are met:
- element is filter,
- callback is
Membrane.Element.WithInputPads.handle_buffer/4
,Membrane.Element.WithInputPads.handle_stream_format/4
,Membrane.Element.Base.handle_event/4
orMembrane.Element.WithInputPads.handle_end_of_stream/3
- playback is
playing
Keep in mind that c:Membrane.WithInputPads.handle_buffer/4
can only
forward buffers, Membrane.Element.WithInputPads.handle_stream_format/4
- stream formats.
Membrane.Element.Base.handle_event/4
- events and
Membrane.Element.WithInputPads.handle_end_of_stream/3
- ends of streams.
@type latency() :: {:latency, latency :: Membrane.Time.non_neg()}
This action sets the latency for the element.
This action is permitted only in callback Membrane.Element.Base.handle_init/2
.
@type notify_parent() :: {:notify_parent, Membrane.ChildNotification.t()}
Sends a message to the parent.
@type pause_auto_demand() :: {:pause_auto_demand, Membrane.Pad.ref() | [Membrane.Pad.ref()]}
Pauses auto-demanding on the specific pad.
The pad must have input direction and work in :auto
flow control mode.
This action does not guarantee that no more buffers will arrive on the specific pad,
but ensures, that demand on this pad will not increase until returning
Membrane.Element.Action.resume_auto_demand()
action. Number of buffers, that will
arrive on the pad, depends on the behaviour of the elements earlier in the pipeline.
When auto-demanding is already paused, this action has no effect.
@type redemand() :: {:redemand, Membrane.Pad.ref() | [Membrane.Pad.ref()]}
Executes Membrane.Element.WithOutputPads.handle_demand/5
callback
for the given pad (or pads), that have demand greater than 0.
The pad must have output direction and work in pull mode.
Redemand in Sources and Endpoints
In case of Sources and Endpoints, :redemand
is just a helper that simplifies element's code.
The element doesn't need to generate the whole demand synchronously at handle_demand
or store current demand size in its state, but it can just generate one buffer
and return :redemand
action.
If there is still one or more buffers to produce, returning :redemand
triggers
the next invocation of handle_demand
. In such case, the element is to produce
next buffer and call :redemand
again.
If there are no more buffers demanded, handle_demand
is not invoked and
the loop ends.
One more advantage of the approach with :redemand
action is that produced buffers
are sent one after another in separate messages and this can possibly improve
the latency.
Redemand in Filters
Redemand in Filters is useful in a situation where not the entire demand of output pad has been satisfied and there is a need to send a demand for additional buffers through the input pad. A typical example of this situation is a parser that has not demanded enough bytes to parse the whole frame.
Usage limitations
Allowed only when playback is playing.
@type resume_auto_demand() :: {:resume_auto_demand, Membrane.Pad.ref() | [Membrane.Pad.ref()]}
Resumes auto-demanding on the specific pad.
The pad must have input direction and work in :auto
flow control mode.
This action reverts the effects of Membrane.Element.Action.pause_auto_demand()
action.
When auto demanding is not paused, this action has no effect.
@type setup() :: {:setup, :incomplete | :complete}
Action that manages the end of the component setup.
By default, component setup ends with the end of Membrane.Element.Base.handle_setup/2
callback.
If {:setup, :incomplete}
is returned there, setup lasts until {:setup, :complete}
is returned from antoher callback.
Untils the setup lasts, the component won't enter :playing
playback.
Allows to split callback execution into multiple applications of another callback (called from now sub-callback).
Executions are synchronous in the element process, and each of them passes subsequent arguments from the args_list, along with the element state (passed as the last argument each time).
Return value of each execution of sub-callback can be any valid return value of the original callback (this also means sub-callback can return any action valid for the original callback, unless explicitly stated). Returned actions are executed immediately (they are NOT accumulated and executed after all sub-callback executions are finished).
Useful when a long action is to be undertaken, and partial results need to be returned before entire process finishes.
@type start_timer() :: {:start_timer, {timer_id :: any(), interval :: Ratio.t() | Membrane.Time.non_neg() | :no_interval} | {timer_id :: any(), interval :: Ratio.t() | Membrane.Time.non_neg() | :no_interval, clock :: Membrane.Clock.t()}}
Starts a timer that will invoke Membrane.Element.Base.handle_tick/3
callback
every interval
according to the given clock
.
The timer's id
is passed to the Membrane.Element.Base.handle_tick/3
callback and can be used for changing its interval via timer_interval/0
or stopping it via stop_timer/0
.
If interval
is set to :no_interval
, the timer won't issue any ticks until
the interval is set with timer_interval/0
action.
If no clock
is passed, parent's clock is chosen.
Timers use Process.send_after/3
under the hood.
@type stop_timer() :: {:stop_timer, timer_id :: any()}
Stops a timer started with start_timer/0
action.
This action is atomic: stopping timer guarantees that no ticks will arrive from it.
@type stream_actions() :: event() | stream_format() | buffer() | demand() | pause_auto_demand() | resume_auto_demand() | end_of_stream() | redemand()
Actions that can be returned from callbacks when the element is in playback: :playing
state.
@type stream_format() :: {:stream_format, {Membrane.Pad.ref(), Membrane.StreamFormat.t()}}
Sends stream format through a pad.
The pad must have output direction. Sent stream format must fit constraints on the pad.
Allowed only when playback is playing
.
@type t() :: common_actions() | stream_actions() | latency() | forward() | setup()
Type that defines a union of actions that may be returned from most of the callbacks.
Depending on element type, callback, current playback and other circumstances there may be different actions available. Check the typespec and documentation of particular callbacks for details.
Terminates element with given reason.
Termination reason follows the OTP semantics:
- Use
:normal
for graceful termination. Allowed only when the parent already requested termination, i.e. afterMembrane.Element.Base.handle_terminate_request/2
is called - If reason is neither
:normal
,:shutdown
nor{:shutdown, term}
, an error is logged
@type timer_interval() :: {:timer_interval, {timer_id :: any(), interval :: Ratio.t() | Membrane.Time.non_neg() | :no_interval}}
Changes interval of a timer started with start_timer/0
.
Permitted only from Membrane.Element.Base.handle_tick/3
, unless the interval
was previously set to :no_interval
.
If the interval
is :no_interval
, the timer won't issue any ticks until
another timer_interval/0
action. Otherwise, the timer will issue ticks every
new interval
. The next tick after interval change is scheduled at
new_interval + previous_time
, where previous_time is the time of the latest
tick or the time of returning start_timer/0
action if no tick has been
sent yet. Note that if current_time - previous_time > new_interval
, a burst
of div(current_time - previous_time, new_interval)
ticks is issued immediately.