Current section

Files

Jump to
membrane_hls_plugin lib membrane hls trimmer.ex
Raw

lib/membrane/hls/trimmer.ex

defmodule Membrane.HLS.Trimmer do
use Membrane.Filter
def_input_pad(:input, accepted_format: _any)
def_output_pad(:output, accepted_format: _any)
@impl true
def handle_init(_ctx, _opts) do
state = %{
queue: :queue.new(),
time_reference: nil
}
{[], state}
end
@impl true
def handle_end_of_stream(:input, _ctx, state = %{time_reference: nil}) do
# We need parent notification first.
{[], state}
end
def handle_end_of_stream(:input, _ctx, state) do
{[end_of_stream: :output], state}
end
@impl true
def handle_buffer(:input, buffer, _ctx, state = %{time_reference: nil}) do
state = update_in(state, [:queue], fn q -> :queue.in(buffer, q) end)
{[], state}
end
def handle_buffer(:input, buffer, _ctx, state) do
{[buffer: {:output, filter_buffers(buffer, state.time_reference)}], state}
end
@impl true
def handle_parent_notification({:time_reference, t}, ctx, state = %{time_reference: nil}) do
{buffers, state} =
get_and_update_in(state, [:queue], fn q ->
{:queue.to_list(q), :queue.new()}
end)
buffers = filter_buffers(buffers, t)
state = put_in(state, [:time_reference], t)
actions =
if ctx.pads.input.end_of_stream? do
[buffer: {:output, buffers}, end_of_stream: :output]
else
[buffer: {:output, buffers}]
end
{actions, state}
end
def handle_parent_notification(_, _ctx, state) do
{[], state}
end
defp filter_buffers(buffer_or_buffers, before) do
buffer_or_buffers
|> List.wrap()
|> Enum.filter(fn x -> Membrane.Buffer.get_dts_or_pts(x) >= before end)
end
end