Packages
membrane_rtp_plugin
0.4.0-alpha
0.31.5
0.31.4
0.31.3
0.31.2
0.31.1
0.31.0
0.30.0
0.29.1
0.29.0
0.28.0
0.27.1
0.27.0
0.26.0
0.25.0
0.24.1
0.24.0
0.23.2
0.23.1
0.23.0
0.22.1
0.22.0
0.21.0
0.20.0
0.19.1
0.19.0
0.18.0
0.17.1
0.17.0
0.16.0
0.15.0
0.15.0-rc.1
0.14.0
0.13.0
0.12.2
0.12.1
0.12.0
0.11.0
0.10.0
0.9.0
0.8.2
0.8.1
0.8.0
0.7.1-alpha.3
0.7.1-alpha.2
0.7.0-alpha.2
0.7.0-alpha.1
0.7.0-alpha
0.6.1
0.6.0
0.5.1
0.5.0
0.4.0-alpha
Membrane Multimedia Framework plugin for RTP
Current section
Files
Jump to
Current section
Files
lib/membrane/rtp/parser.ex
defmodule Membrane.RTP.Parser do
@moduledoc """
Parses RTP packets.
See `options/0` for available options
"""
use Membrane.Filter
alias Membrane.Buffer
alias Membrane.Element.Action
alias Membrane.RTP
alias Membrane.RTP.{Header, Packet}
@metadata_fields [:timestamp, :sequence_number, :ssrc, :payload_type]
def_output_pad :output,
caps: RTP
def_input_pad :input,
caps: :any,
demand_unit: :buffers
defmodule State do
@moduledoc false
defstruct payload_type: nil
@type t :: %__MODULE__{
payload_type: RTP.payload_type_t() | nil
}
end
@impl true
def handle_init(_) do
{:ok, %State{}}
end
@impl true
def handle_process(:input, %Buffer{payload: buffer_payload} = buffer, _ctx, state) do
with {:ok, %Packet{} = packet} <- Packet.parse(buffer_payload),
{commands, state} <- build_commands(packet, buffer, state) do
{{:ok, commands}, state}
else
{:error, reason} ->
{{:error, reason}, state}
end
end
@impl true
def handle_demand(:output, size, _unit, _ctx, state) do
{{:ok, demand: {:input, size}}, state}
end
@spec build_commands(Packet.t(), Buffer.t(), State.t()) :: {[Action.t()], State.t()}
defp build_commands(packet, buffer, state)
defp build_commands(%Packet{} = packet, buffer, %State{payload_type: nil} = state) do
%Packet{header: %Header{payload_type: pt}} = packet
{commands, state} = build_commands(packet, buffer, %State{state | payload_type: pt})
caps = build_caps(packet)
{[caps | commands], state}
end
defp build_commands(packet, buffer, %State{payload_type: _} = state) do
buffer = build_buffer(buffer, packet)
commands = [buffer: {:output, buffer}]
{commands, state}
end
@spec build_caps(Packet.t()) :: Action.caps_t()
defp build_caps(%Packet{header: header}) do
%Header{
payload_type: payload_type
} = header
caps = %RTP{
payload_type: payload_type
}
{:caps, {:output, caps}}
end
@spec build_buffer(Buffer.t(), Packet.t()) :: Buffer.t()
defp build_buffer(
%Buffer{metadata: metadata} = original_buffer,
%Packet{payload: payload} = packet
) do
updated_metadata = build_metadata(packet, metadata)
%Buffer{original_buffer | payload: payload, metadata: updated_metadata}
end
@spec build_metadata(Packet.t(), map()) :: map()
defp build_metadata(%Packet{header: %Header{} = header}, metadata) do
extracted = Map.take(header, @metadata_fields)
Map.put(metadata, :rtp, extracted)
end
end