Current section

Files

Jump to
membrane_rtp_plugin lib membrane rtcp packet.ex
Raw

lib/membrane/rtcp/packet.ex

defmodule Membrane.RTCP.Packet do
@moduledoc """
Functions common to all RTCP Packets
"""
alias Membrane.RTCP.{
AppPacket,
ByePacket,
Header,
ReceiverReportPacket,
SdesPacket,
SenderReportPacket
}
@type t ::
AppPacket.t()
| ByePacket.t()
| ReceiverReportPacket.t()
| SenderReportPacket.t()
| SdesPacket.t()
# TODO: Remove if it won't be used by SRTCP
# @doc """
# Adds a padding to align body to a 32 bit boundary
# """
# @spec align(binary()) :: binary()
# def align(body) do
# case body |> bit_size |> rem(32) do
# 0 ->
# body
# unaligned_bits ->
# pad_bits = 32 - unaligned_bits
# end_pad = <<0::size(pad_bits)>>
# body <> end_pad
# end
# end
#
@doc """
Converts packet structure into binary
"""
@spec to_binary(t()) :: binary()
def to_binary(%packet_module{} = packet) do
{body, packet_type, packet_specific} = packet_module.encode(packet)
length = body |> byte_size() |> div(4)
# `length` is simplified from `length - 1 + 1` to include header size
header = <<2::2, 0::1, packet_specific::5, packet_type::8, length::16>>
header <> body
end
@doc """
Parses packet body using data from parsed header
"""
@spec parse_body(binary(), Header.t()) :: {:ok, t()} | {:error, reason :: atom()}
def parse_body(packet, %{packet_type: pt, packet_specific: packet_specific}) do
with {:ok, packet_module} <- decode_packet_type(pt) do
packet_module.decode(packet, packet_specific)
end
end
defp decode_packet_type(200), do: {:ok, SenderReportPacket}
defp decode_packet_type(201), do: {:ok, ReceiverReportPacket}
defp decode_packet_type(202), do: {:ok, SdesPacket}
defp decode_packet_type(203), do: {:ok, ByePacket}
defp decode_packet_type(204), do: {:ok, AppPacket}
defp decode_packet_type(_pt), do: {:error, :unknown_pt}
defdelegate strip_padding(body, present?), to: Membrane.RTP.Packet
@doc """
Decodes binary with packet body (without header) into packet struct. Used by `parse/1`
"""
@callback decode(binary(), packet_specific :: Header.packet_specific_t()) ::
{:ok, struct()} | {:error, atom()}
@doc """
Encodes packet struct into the tuple used by `to_binary/1`
"""
@callback encode(struct()) ::
{body :: binary(), packet_type :: Header.packet_type_t(),
packet_specific :: Header.packet_specific_t()}
end