Skip to content

Commit 6a8989d

Browse files
committed
add tests, fix depayloader
1 parent ac52333 commit 6a8989d

File tree

2 files changed

+102
-19
lines changed

2 files changed

+102
-19
lines changed

lib/ex_webrtc/rtp/h264/depayloader.ex

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ defmodule ExWebRTC.RTP.Depayloader.H264 do
4242
Resetting depayloader state. Payload: #{inspect(packet.payload)}.\
4343
""")
4444

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

@@ -58,27 +58,27 @@ defmodule ExWebRTC.RTP.Depayloader.H264 do
5858
{header, payload}
5959
) do
6060
if fu_parser_acc != nil and current_timestamp != packet.timestamp do
61-
{:error, "Invalid timestamp inside FU-A"}
62-
63-
Logger.debug("""
61+
Logger.warning("""
6462
Received packet with FU-A type payload that is not a start of Fragmentation Unit with timestamp \
6563
different than last start and without finishing the previous FU. Dropping FU.\
6664
""")
67-
end
6865

69-
case FU.parse(payload, fu_parser_acc || %FU{}) do
70-
{:ok, {data, type}} ->
71-
data = NAL.Header.add_header(data, 0, header.nal_ref_idc, type)
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)
7271

73-
{:ok,
74-
{prefix_annexb(data),
75-
%__MODULE__{current_timestamp: packet.timestamp, fu_parser_acc: nil}}}
72+
{:ok,
73+
{prefix_annexb(data),
74+
%__MODULE__{current_timestamp: packet.timestamp, fu_parser_acc: nil}}}
7675

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

80-
{:error, _reason} = error ->
81-
error
79+
{:error, _reason} = error ->
80+
error
81+
end
8282
end
8383
end
8484

@@ -90,11 +90,11 @@ defmodule ExWebRTC.RTP.Depayloader.H264 do
9090
end
9191

9292
defp handle_unit_type(unsupported_type, _depayloader, _packet, _nal) do
93-
{:error, "Unsupported nal type #{unsupported_type}"}
94-
95-
Logger.debug("""
96-
Received packet with unsupported NAL type. Supported types are: Single NALU, STAP-A, FU-A. Dropping packet.
93+
Logger.warning("""
94+
Received packet with unsupported NAL type: #{unsupported_type}. Supported types are: Single NALU, STAP-A, FU-A. Dropping packet.
9795
""")
96+
97+
{:error, "Unsupported nal type #{unsupported_type}"}
9898
end
9999

100100
defp prefix_annexb(nal) do
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
defmodule ExWebRTC.RTP.H264.DepayloaderTest do
2+
use ExUnit.Case, async: true
3+
4+
alias ExWebRTC.RTP.Depayloader
5+
6+
test "depayload/2" do
7+
payload_stapa = <<56, 0, 1, 128, 0, 1, 129>>
8+
payload_stapa_out = <<0, 0, 0, 1, 128, 0, 0, 0, 1, 129>>
9+
10+
payload_fuas = <<60, 133, 128>>
11+
payload_fua = <<60, 5, 129>>
12+
payload_fuae = <<60, 69, 130>>
13+
payload_fua_out = <<0, 0, 0, 1, 37, 128, 129, 130>>
14+
15+
payload_single = <<53, 131>>
16+
payload_single_out = <<0, 0, 0, 1, 131>>
17+
18+
# reserved NALu types (22, 23, 30, 31)
19+
payloads_nalu_reserved = [<<55, 131>>, <<56, 131>>, <<62, 131>>, <<63, 131>>]
20+
# malformed STAP-A payload. First NAL should be 1-byte long, but is 2-bytes long
21+
payload_invalid = <<56, 0, 1, 128, 12, 0, 1, 129>>
22+
23+
depayloader = Depayloader.H264.new()
24+
25+
# Single NAL Unit
26+
packet = ExRTP.Packet.new(payload_single, timestamp: 123)
27+
28+
assert {^payload_single_out, %{current_timestamp: 123, fu_parser_acc: nil}} =
29+
Depayloader.H264.depayload(depayloader, packet)
30+
31+
# STAP-A NAL
32+
packet = ExRTP.Packet.new(payload_stapa, timestamp: 123)
33+
34+
assert {^payload_stapa_out, %{current_timestamp: 123, fu_parser_acc: nil}} =
35+
Depayloader.H264.depayload(depayloader, packet)
36+
37+
# FU-A NAL
38+
packet1 = ExRTP.Packet.new(payload_fuas, timestamp: 10)
39+
packet2 = ExRTP.Packet.new(payload_fua, timestamp: 10)
40+
packet3 = ExRTP.Packet.new(payload_fuae, timestamp: 10)
41+
42+
{bin, depayloader} = Depayloader.H264.depayload(depayloader, packet1)
43+
44+
assert {nil, %{current_timestamp: 10, fu_parser_acc: %{data: [<<128>>]}}} =
45+
{bin, depayloader}
46+
47+
{bin, depayloader} = Depayloader.H264.depayload(depayloader, packet2)
48+
49+
assert {nil, %{current_timestamp: 10, fu_parser_acc: %{data: [<<129>>, <<128>>]}}} =
50+
{bin, depayloader}
51+
52+
assert {^payload_fua_out, %{current_timestamp: 10, fu_parser_acc: nil}} =
53+
Depayloader.H264.depayload(depayloader, packet3)
54+
55+
# Colliding timestamps in one FU-A
56+
packet1 = ExRTP.Packet.new(payload_fuas, timestamp: 10)
57+
packet2 = ExRTP.Packet.new(payload_fua, timestamp: 11)
58+
59+
{bin, depayloader} = Depayloader.H264.depayload(depayloader, packet1)
60+
61+
assert {nil, %{current_timestamp: 10, fu_parser_acc: %{data: [<<128>>]}}} =
62+
{bin, depayloader}
63+
64+
{bin, depayloader} = Depayloader.H264.depayload(depayloader, packet2)
65+
66+
assert {nil, %{current_timestamp: nil, fu_parser_acc: nil}} =
67+
{bin, depayloader}
68+
69+
# Check all reserved NAL types
70+
Enum.map(payloads_nalu_reserved, fn payload ->
71+
packet = ExRTP.Packet.new(payload, timestamp: 123)
72+
73+
assert {nil, %{current_timestamp: nil, fu_parser_acc: nil}} =
74+
Depayloader.H264.depayload(depayloader, packet)
75+
end)
76+
77+
# Check malformed NAL
78+
packet = ExRTP.Packet.new(payload_invalid, timestamp: 123)
79+
80+
assert {nil, %{current_timestamp: nil, fu_parser_acc: nil}} =
81+
Depayloader.H264.depayload(depayloader, packet)
82+
end
83+
end

0 commit comments

Comments
 (0)