Current section

Files

Jump to
membrane_rtp_plugin lib membrane rtp parser.ex
Raw

lib/membrane/rtp/parser.ex

defmodule Membrane.RTP.Parser do
@moduledoc """
Parses RTP packets.
Outputs each packet payload as a separate `Membrane.Buffer`.
Attaches the following metadata under `:rtp` key: `:timestamp`, `:sequence_number`,
`:ssrc`, `:payload_type`, `:marker`, `:extension`. See `Membrane.RTP.Header` for
their meaning and specifications.
"""
use Membrane.Filter
alias Membrane.Buffer
alias Membrane.{RTP, RemoteStream}
alias Membrane.RTP.{Header, Packet}
@metadata_fields [
:timestamp,
:sequence_number,
:ssrc,
:csrcs,
:payload_type,
:marker,
:extension
]
def_input_pad :input,
caps: {RemoteStream, type: :packetized, content_format: one_of([nil, RTP])},
demand_unit: :buffers
def_output_pad :output, caps: RTP
@impl true
def handle_init(_opts) do
{:ok, %{}}
end
@impl true
def handle_caps(:input, _caps, _ctx, state) do
{{:ok, caps: {:output, %RTP{}}}, state}
end
@impl true
def handle_process(:input, %Buffer{payload: buffer_payload} = buffer, _ctx, state) do
with {:ok, %Packet{} = packet} <- Packet.parse(buffer_payload) do
{{:ok, buffer: {:output, build_buffer(buffer, packet)}}, state}
else
{:error, reason} -> {{:error, reason}, state}
end
end
@impl true
def handle_demand(:output, size, :buffers, _ctx, state) do
{{:ok, demand: {:input, size}}, state}
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