/
header.ex
65 lines (53 loc) · 1.73 KB
/
header.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
55
56
57
58
59
60
61
62
63
64
65
defmodule Membrane.RTP.H264.FU.Header do
@moduledoc """
Defines a structure representing Fragmentation Unit (FU) header
which is defined in [RFC6184](https://tools.ietf.org/html/rfc6184#page-31)
```
+---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|S|E|R| Type |
+---------------+
```
"""
alias Membrane.RTP.H264.NAL
@typedoc """
MUST be set to true only in the first packet in a sequence.
"""
@type start_flag :: boolean()
@typedoc """
MUST be set to true only in the last packet in a sequence.
"""
@type end_flag :: boolean()
@enforce_keys [:type]
defstruct start_bit: false, end_bit: false, type: 0
@type t :: %__MODULE__{
start_bit: start_flag(),
end_bit: end_flag(),
type: NAL.Header.type()
}
defguardp valid_frame_boundary(start, finish) when start != 1 or finish != 1
@doc """
Parses Fragmentation Unit Header
It will fail if the Start bit and End bit are both set to one in the
same Fragmentation Unit Header, because a fragmented NAL unit
MUST NOT be transmitted in one FU.
"""
@spec parse(data :: binary()) :: {:error, :packet_malformed} | {:ok, {t(), nal :: binary()}}
def parse(<<start::1, finish::1, 0::1, nal_type::5, rest::binary>>)
when nal_type in 1..23 and valid_frame_boundary(start, finish) do
header = %__MODULE__{
start_bit: start == 1,
end_bit: finish == 1,
type: nal_type
}
{:ok, {header, rest}}
end
def parse(_binary), do: {:error, :packet_malformed}
@doc """
Adds FU header
"""
@spec add_header(binary(), 0 | 1, 0 | 1, NAL.Header.type()) :: binary()
def add_header(payload, start_bit, end_bit, type),
do: <<start_bit::1, end_bit::1, 0::1, type::5>> <> payload
end