defmodule Membrane.RTCP.Header do @moduledoc """ Struct describing 32-bit header common to all RTCP packets """ @enforce_keys [:packet_type, :packet_specific] defstruct @enforce_keys @type packet_type_t :: 200..204 @type packet_specific_t :: non_neg_integer() @type t :: %__MODULE__{ packet_specific: packet_specific_t(), packet_type: packet_type_t() } @spec parse(binary()) :: {:ok, %{header: t(), padding?: boolean, body_size: pos_integer}} | :error def parse(<<2::2, padding::1, packet_specific::5, pt::8, length::16>>) do {:ok, %{ header: %__MODULE__{ packet_specific: packet_specific, packet_type: pt }, padding?: padding == 1, body_size: length * 4 }} end def parse(_binary) do :error end @spec serialize(t(), body_size: pos_integer(), padding?: boolean()) :: binary() def serialize(%__MODULE__{} = header, opts) do padding = if Keyword.get(opts, :padding?), do: 1, else: 0 size = Keyword.fetch!(opts, :body_size) unless rem(size, 4) == 0 do raise "RTCP packet body size must be divisible by 4, got: #{size}" end <<2::2, padding::1, header.packet_specific::5, header.packet_type::8, div(size, 4)::16>> end end