/
feedback_packet.ex
54 lines (43 loc) · 1.61 KB
/
feedback_packet.ex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
defmodule Membrane.RTCP.FeedbackPacket do
@moduledoc """
Abstraction and generic encoding/decoding functionality for
[RTCP payload-specific feedback packets](https://datatracker.ietf.org/doc/html/rfc5104#section-4.3).
"""
@behaviour Membrane.RTCP.Packet
alias Membrane.RTP
@enforce_keys [:origin_ssrc, :payload]
defstruct @enforce_keys ++ [target_ssrc: 0]
@type t :: %__MODULE__{
origin_ssrc: RTP.ssrc_t(),
target_ssrc: RTP.ssrc_t(),
payload: struct
}
@callback decode(binary()) :: {:ok, struct()} | {:error, any()}
@callback encode(struct()) :: binary()
@packet_type_payload BiMap.new(%{
1 => __MODULE__.PLI,
4 => __MODULE__.FIR,
15 => __MODULE__.AFB
})
@impl true
def decode(<<origin_ssrc::32, target_ssrc::32, payload::binary>>, packet_type) do
with {:ok, module} <- BiMap.fetch(@packet_type_payload, packet_type),
{:ok, payload} <- module.decode(payload) do
{:ok, %__MODULE__{origin_ssrc: origin_ssrc, target_ssrc: target_ssrc, payload: payload}}
else
:error -> {:error, {:unknown_feedback_packet_type, packet_type}}
{:error, reason} -> {:error, reason}
end
end
@impl true
def decode(_binary, _packet_type) do
{:error, :malformed_packet}
end
@impl true
def encode(%__MODULE__{} = packet) do
%module{} = packet.payload
packet_type = BiMap.fetch_key!(@packet_type_payload, module)
{<<packet.origin_ssrc::32, packet.target_ssrc::32, module.encode(packet.payload)::binary>>,
packet_type}
end
end