Skip to content

Commit 43407a3

Browse files
committed
review fixes, unused code removal
1 parent 7353165 commit 43407a3

File tree

6 files changed

+88
-139
lines changed

6 files changed

+88
-139
lines changed

lib/ex_webrtc/rtp/h264/depayloader.ex

Lines changed: 41 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
defmodule ExWebRTC.RTP.Depayloader.H264 do
2-
@moduledoc """
3-
Extracts H264 NAL Units from RTP packets.
2+
@moduledoc false
3+
# Extracts H264 NAL Units from RTP packets.
4+
#
5+
# Based on [RFC 6184](https://tools.ietf.org/html/rfc6184).
6+
#
7+
# Supported types: Single NALU, FU-A, STAP-A.
48

5-
Based on [RFC 6184](https://tools.ietf.org/html/rfc6184).
6-
7-
Supported types: Single NALU, FU-A, STAP-A.
8-
"""
99
@behaviour ExWebRTC.RTP.Depayloader.Behaviour
1010

1111
require Logger
@@ -15,11 +15,11 @@ defmodule ExWebRTC.RTP.Depayloader.H264 do
1515
@annexb_prefix <<1::32>>
1616

1717
@type t() :: %__MODULE__{
18-
current_timestamp: nil,
19-
fu_parser_acc: nil
18+
current_timestamp: non_neg_integer() | nil,
19+
fu_parser_acc: [binary()]
2020
}
2121

22-
defstruct [:current_timestamp, :fu_parser_acc]
22+
defstruct current_timestamp: nil, fu_parser_acc: []
2323

2424
@impl true
2525
def new() do
@@ -33,7 +33,7 @@ defmodule ExWebRTC.RTP.Depayloader.H264 do
3333
with {:ok, {header, _payload} = nal} <- NAL.Header.parse_unit_header(packet.payload),
3434
unit_type = NAL.Header.decode_type(header),
3535
{:ok, {nal, depayloader}} <-
36-
handle_unit_type(unit_type, depayloader, packet, nal) do
36+
do_depayload(unit_type, depayloader, packet, nal) do
3737
{nal, depayloader}
3838
else
3939
{:error, reason} ->
@@ -42,54 +42,60 @@ defmodule ExWebRTC.RTP.Depayloader.H264 do
4242
Resetting depayloader state. Payload: #{inspect(packet.payload)}.\
4343
""")
4444

45-
{nil, %{depayloader | current_timestamp: nil, fu_parser_acc: nil}}
45+
{nil, %{depayloader | current_timestamp: nil, fu_parser_acc: []}}
4646
end
4747
end
4848

49-
defp handle_unit_type(:single_nalu, depayloader, packet, {_header, payload}) do
49+
defp do_depayload(:single_nalu, depayloader, packet, {_header, payload}) do
5050
{:ok,
5151
{prefix_annexb(payload), %__MODULE__{depayloader | current_timestamp: packet.timestamp}}}
5252
end
5353

54-
defp handle_unit_type(
54+
defp do_depayload(
5555
:fu_a,
5656
%{current_timestamp: current_timestamp, fu_parser_acc: fu_parser_acc},
5757
packet,
58+
{_header, _payload}
59+
)
60+
when fu_parser_acc != [] and current_timestamp != packet.timestamp do
61+
Logger.warning("""
62+
received packet with fu-a type payload that is not a start of fragmentation unit with timestamp \
63+
different than last start and without finishing the previous fu. dropping fu.\
64+
""")
65+
66+
{:error, "invalid timestamp inside fu-a"}
67+
end
68+
69+
defp do_depayload(
70+
:fu_a,
71+
%{fu_parser_acc: fu_parser_acc},
72+
packet,
5873
{header, payload}
5974
) do
60-
if fu_parser_acc != nil and current_timestamp != packet.timestamp do
61-
Logger.warning("""
62-
Received packet with FU-A type payload that is not a start of Fragmentation Unit with timestamp \
63-
different than last start and without finishing the previous FU. Dropping FU.\
64-
""")
65-
66-
{:error, "Invalid timestamp inside FU-A"}
67-
else
68-
case FU.parse(payload, fu_parser_acc || %FU{}) do
69-
{:ok, {data, type}} ->
70-
data = NAL.Header.add_header(data, 0, header.nal_ref_idc, type)
75+
case FU.parse(payload, fu_parser_acc || []) do
76+
{:ok, {data, type}} ->
77+
data = NAL.Header.add_header(data, 0, header.nal_ref_idc, type)
7178

72-
{:ok,
73-
{prefix_annexb(data),
74-
%__MODULE__{current_timestamp: packet.timestamp, fu_parser_acc: nil}}}
79+
{:ok,
80+
{prefix_annexb(data),
81+
%__MODULE__{current_timestamp: packet.timestamp, fu_parser_acc: []}}}
7582

76-
{:incomplete, fu} ->
77-
{:ok, {nil, %__MODULE__{fu_parser_acc: fu, current_timestamp: packet.timestamp}}}
83+
{:incomplete, fu} ->
84+
{:ok, {nil, %__MODULE__{fu_parser_acc: fu, current_timestamp: packet.timestamp}}}
7885

79-
{:error, _reason} = error ->
80-
error
81-
end
86+
{:error, _reason} = error ->
87+
error
8288
end
8389
end
8490

85-
defp handle_unit_type(:stap_a, depayloader, packet, {_header, payload}) do
91+
defp do_depayload(:stap_a, depayloader, packet, {_header, payload}) do
8692
with {:ok, result} <- StapA.parse(payload) do
87-
nals = Enum.reduce(result, <<>>, fn nal, acc -> acc <> prefix_annexb(nal) end)
93+
nals = result |> Stream.map(&prefix_annexb/1) |> Enum.join()
8894
{:ok, {nals, %__MODULE__{depayloader | current_timestamp: packet.timestamp}}}
8995
end
9096
end
9197

92-
defp handle_unit_type(unsupported_type, _depayloader, _packet, _nal) do
98+
defp do_depayload(unsupported_type, _depayloader, _packet, _nal) do
9399
Logger.warning("""
94100
Received packet with unsupported NAL type: #{unsupported_type}. Supported types are: Single NALU, STAP-A, FU-A. Dropping packet.
95101
""")

lib/ex_webrtc/rtp/h264/nal_formats/fu.ex

Lines changed: 8 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,9 @@ defmodule ExWebRTC.RTP.H264.FU do
22
@moduledoc """
33
Module responsible for parsing H264 Fragmentation Unit.
44
"""
5-
use Bunch
65
alias __MODULE__
76
alias ExWebRTC.RTP.H264.NAL
87

9-
defstruct data: []
10-
11-
@type t :: %__MODULE__{data: [binary()]}
12-
138
@doc """
149
Parses H264 Fragmentation Unit
1510
@@ -18,68 +13,28 @@ defmodule ExWebRTC.RTP.H264.FU do
1813
In case of last packet `{:ok, {type, data}}` tuple will be returned, where data
1914
is `NAL Unit` created by concatenating subsequent Fragmentation Units.
2015
"""
21-
@spec parse(binary(), t) ::
16+
@spec parse(binary(), [binary()]) ::
2217
{:ok, {binary(), NAL.Header.type()}}
2318
| {:error, :packet_malformed | :invalid_first_packet}
24-
| {:incomplete, t()}
19+
| {:incomplete, [binary()]}
2520
def parse(packet, acc) do
2621
with {:ok, {header, value}} <- FU.Header.parse(packet) do
2722
do_parse(header, value, acc)
2823
end
2924
end
3025

31-
@doc """
32-
Serialize H264 unit into list of FU-A payloads
33-
"""
34-
@spec serialize(binary(), pos_integer()) :: list(binary()) | {:error, :unit_too_small}
35-
def serialize(data, preferred_size) do
36-
case data do
37-
<<header::1-binary, head::binary-size(preferred_size - 1), rest::binary>> ->
38-
<<r::1, nri::2, type::5>> = header
39-
40-
payload =
41-
head
42-
|> FU.Header.add_header(1, 0, type)
43-
|> NAL.Header.add_header(r, nri, NAL.Header.encode_type(:fu_a))
44-
45-
[payload | do_serialize(rest, r, nri, type, preferred_size)]
46-
47-
_data ->
48-
{:error, :unit_too_small}
49-
end
50-
end
51-
52-
defp do_serialize(data, r, nri, type, preferred_size) do
53-
case data do
54-
<<head::binary-size(preferred_size - 2), rest::binary>> when byte_size(rest) > 0 ->
55-
payload =
56-
head
57-
|> FU.Header.add_header(0, 0, type)
58-
|> NAL.Header.add_header(r, nri, NAL.Header.encode_type(:fu_a))
59-
60-
[payload] ++ do_serialize(rest, r, nri, type, preferred_size)
61-
62-
rest ->
63-
[
64-
rest
65-
|> FU.Header.add_header(0, 1, type)
66-
|> NAL.Header.add_header(r, nri, NAL.Header.encode_type(:fu_a))
67-
]
68-
end
69-
end
70-
7126
defp do_parse(header, packet, acc)
7227

73-
defp do_parse(%FU.Header{start_bit: true}, data, %{data: []} = acc),
74-
do: {:incomplete, %__MODULE__{acc | data: [data]}}
28+
defp do_parse(%FU.Header{start_bit: true}, data, []),
29+
do: {:incomplete, [data]}
7530

7631
defp do_parse(%FU.Header{start_bit: true}, _data, _acc),
7732
do: {:error, :last_fu_not_finished}
7833

79-
defp do_parse(%FU.Header{start_bit: false}, _data, %__MODULE__{data: []}),
34+
defp do_parse(%FU.Header{start_bit: false}, _data, []),
8035
do: {:error, :invalid_first_packet}
8136

82-
defp do_parse(%FU.Header{end_bit: true, type: type}, data, %__MODULE__{data: acc_data}) do
37+
defp do_parse(%FU.Header{end_bit: true, type: type}, data, acc_data) do
8338
result =
8439
[data | acc_data]
8540
|> Enum.reverse()
@@ -88,6 +43,6 @@ defmodule ExWebRTC.RTP.H264.FU do
8843
{:ok, {result, type}}
8944
end
9045

91-
defp do_parse(_header, data, %__MODULE__{data: acc_data} = fu),
92-
do: {:incomplete, %__MODULE__{fu | data: [data | acc_data]}}
46+
defp do_parse(_header, data, acc_data),
47+
do: {:incomplete, [data | acc_data]}
9348
end

lib/ex_webrtc/rtp/h264/nal_formats/stap_a.ex

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@ defmodule ExWebRTC.RTP.H264.StapA do
2424
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2525
```
2626
"""
27-
use Bunch
28-
2927
alias ExWebRTC.RTP.H264.NAL
3028

3129
@spec parse(binary()) :: {:ok, [binary()]} | {:error, :packet_malformed}
@@ -39,16 +37,4 @@ defmodule ExWebRTC.RTP.H264.StapA do
3937
do: do_parse(rest, [nalu | acc])
4038

4139
defp do_parse(_data, _acc), do: {:error, :packet_malformed}
42-
43-
@spec aggregation_unit_size(binary()) :: pos_integer()
44-
def aggregation_unit_size(nalu), do: byte_size(nalu) + 2
45-
46-
@spec serialize([binary], 0..1, 0..3) :: binary
47-
def serialize(payloads, f, nri) do
48-
payloads
49-
|> Enum.reverse()
50-
|> Enum.map(&<<byte_size(&1)::16, &1::binary>>)
51-
|> IO.iodata_to_binary()
52-
|> NAL.Header.add_header(f, nri, NAL.Header.encode_type(:stap_a))
53-
end
5440
end

lib/ex_webrtc/rtp/h264/nal_header.ex

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ defmodule ExWebRTC.RTP.H264.NAL.Header do
4444
| Reserved | 30-31 |
4545
4646
"""
47-
@type type :: 1..31
47+
@type rbsp_type :: 1..31
4848
@type supported_types :: :stap_a | :fu_a | :single_nalu
4949
@type unsupported_types :: :stap_b | :mtap_16 | :mtap_24 | :fu_b
5050
@type types :: supported_types | unsupported_types | :reserved
@@ -53,7 +53,7 @@ defmodule ExWebRTC.RTP.H264.NAL.Header do
5353

5454
@type t :: %__MODULE__{
5555
nal_ref_idc: nri(),
56-
type: type()
56+
type: rbsp_type()
5757
}
5858

5959
@spec parse_unit_header(binary()) :: {:error, :malformed_data} | {:ok, {t(), binary()}}
@@ -74,7 +74,7 @@ defmodule ExWebRTC.RTP.H264.NAL.Header do
7474
@doc """
7575
Adds NAL header to payload
7676
"""
77-
@spec add_header(binary(), 0 | 1, nri(), type()) :: binary()
77+
@spec add_header(binary(), 0 | 1, nri(), rbsp_type()) :: binary()
7878
def add_header(payload, f, nri, type),
7979
do: <<f::1, nri::2, type::5>> <> payload
8080

@@ -94,17 +94,4 @@ defmodule ExWebRTC.RTP.H264.NAL.Header do
9494
defp do_decode_type(29), do: :fu_b
9595
defp do_decode_type(number) when number in [30, 31], do: :reserved
9696
defp do_decode_type(_), do: :invalid
97-
98-
@doc """
99-
Encodes given NAL type
100-
"""
101-
@spec encode_type(types()) :: type()
102-
def encode_type(:single_nalu), do: 1
103-
def encode_type(:stap_a), do: 24
104-
def encode_type(:stap_b), do: 25
105-
def encode_type(:mtap_16), do: 26
106-
def encode_type(:mtap_24), do: 27
107-
def encode_type(:fu_a), do: 28
108-
def encode_type(:fu_b), do: 29
109-
def encode_type(:reserved), do: 30
11097
end

test/ex_webrtc/rtp/depayloader_test.exs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,4 +83,10 @@ defmodule ExWebRTC.RTP.DepayloaderTest do
8383
assert Depayloader.depayload(depayloader, @packet) ==
8484
Depayloader.H264.depayload(depayloader, @packet)
8585
end
86+
87+
test "returns error if no depayloader exists for given codec" do
88+
assert {:error, :no_depayloader_for_codec} =
89+
%RTPCodecParameters{payload_type: 45, mime_type: "video/AV1", clock_rate: 90_000}
90+
|> Depayloader.new()
91+
end
8692
end

0 commit comments

Comments
 (0)