Current section

Files

Jump to
membrane_core lib membrane tee.ex
Raw

lib/membrane/tee.ex

defmodule Membrane.Tee do
@moduledoc """
Element for forwarding buffers to at least one output pad
It has one input pad `:input` and 2 output pads:
* `:output` - is a dynamic pad which is always available and works in pull mode
* `:push_output` - is a dynamic pad that can be linked to any number of elements (including 0) and works
in push mode
The `:output` pads dictate the speed of processing data and any element (or elements) connected to
`:push_output` pad will receive the same data as all `:output` instances.
"""
use Membrane.Filter, flow_control_hints?: false
require Membrane.Logger
def_input_pad :input,
availability: :always,
flow_control: :auto,
accepted_format: _any
def_output_pad :output,
availability: :on_request,
flow_control: :auto,
accepted_format: _any
def_output_pad :push_output,
availability: :on_request,
flow_control: :push,
accepted_format: _any
@impl true
def handle_init(_ctx, _opts) do
{[], %{stream_format: nil}}
end
@impl true
def handle_playing(ctx, state) do
if map_size(ctx.pads) < 2 do
Membrane.Logger.debug("""
#{inspect(__MODULE__)} enters :playing playback without any output (:output or :push_output) \
pads linked.
""")
end
{[], state}
end
@impl true
def handle_stream_format(:input, stream_format, _ctx, state) do
{[broadcast: stream_format], %{state | stream_format: stream_format}}
end
@impl true
def handle_pad_added(Pad.ref(name, _ref) = output_pad, ctx, state)
when name in [:output, :push_output] do
maybe_stream_format =
case state.stream_format do
nil -> []
stream_format -> [stream_format: {output_pad, stream_format}]
end
maybe_eos =
if ctx.pads.input.end_of_stream?,
do: [end_of_stream: output_pad],
else: []
{maybe_stream_format ++ maybe_eos, state}
end
@impl true
def handle_buffer(:input, buffer, _ctx, state) do
{[broadcast: buffer], state}
end
end