Skip to content

Commit 8b38a10

Browse files
committed
Add tests
1 parent bc4a103 commit 8b38a10

File tree

4 files changed

+176
-22
lines changed

4 files changed

+176
-22
lines changed

lib/ex_webrtc/rtp_sender.ex

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ defmodule ExWebRTC.RTPSender do
2121
mid: String.t() | nil,
2222
pt: non_neg_integer() | nil,
2323
rtx_pt: non_neg_integer() | nil,
24-
# ssrc and rtx_ssrc are always present, even if there is no track
24+
# ssrc and rtx_ssrc are always present, even if there is no track,
2525
# or transceiver direction is recvonly.
2626
# We preallocate them so they can be included in SDP when needed.
2727
ssrc: non_neg_integer(),
@@ -140,8 +140,8 @@ defmodule ExWebRTC.RTPSender do
140140
msid_attrs =
141141
case sender.track do
142142
nil ->
143-
# In theory, we should do this "for each MediaStream that was associated with the transceiver"
144-
# but web browsers (chrome, ff), include MSID even when there aren't any MediaStreams
143+
# In theory, we should do this "for each MediaStream that was associated with the transceiver",
144+
# but web browsers (chrome, ff) include MSID even when there aren't any MediaStreams
145145
[ExSDP.Attribute.MSID.new("-", nil)]
146146

147147
%MediaStreamTrack{streams: streams} ->
@@ -192,13 +192,10 @@ defmodule ExWebRTC.RTPSender do
192192
streams ->
193193
{ssrc_attrs, rtx_ssrc_attrs} =
194194
Enum.reduce(streams, {[], []}, fn stream, {ssrc_attrs, rtx_ssrc_attrs} ->
195-
ssrc_attr = [%ExSDP.Attribute.SSRC{id: ssrc, attribute: "msid", value: stream}]
195+
ssrc_attr = %ExSDP.Attribute.SSRC{id: ssrc, attribute: "msid", value: stream}
196196
ssrc_attrs = [ssrc_attr | ssrc_attrs]
197197

198-
rtx_ssrc_attr = [
199-
%ExSDP.Attribute.SSRC{id: rtx_ssrc, attribute: "msid", value: stream}
200-
]
201-
198+
rtx_ssrc_attr = %ExSDP.Attribute.SSRC{id: rtx_ssrc, attribute: "msid", value: stream}
202199
rtx_ssrc_attrs = [rtx_ssrc_attr | rtx_ssrc_attrs]
203200

204201
{ssrc_attrs, rtx_ssrc_attrs}

lib/ex_webrtc/rtp_sender/nack_responder.ex

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,12 @@ defmodule ExWebRTC.RTPSender.NACKResponder do
2828

2929
{packets, seq_no} =
3030
seq_nos
31-
|> Enum.map(fn seq_no -> {seq_no, Map.get(responder.packets, rem(seq_no, @max_packets))} end)
32-
|> Enum.filter(fn {seq_no, packet} -> packet != nil and packet.sequence_number == seq_no end)
31+
|> Enum.map(fn seq_no ->
32+
{seq_no, Map.get(responder.packets, rem(seq_no, @max_packets))}
33+
end)
34+
|> Enum.filter(fn {seq_no, packet} ->
35+
packet != nil and packet.sequence_number == seq_no
36+
end)
3337
# ssrc will be assigned by the sender
3438
|> Enum.map_reduce(responder.seq_no, fn {seq_no, packet}, rtx_seq_no ->
3539
rtx_packet = %Packet{

test/ex_webrtc/rtp_sender_test.exs

Lines changed: 80 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,28 @@ defmodule ExWebRTC.RTPSenderTest do
99
@ssrc 354_947
1010
@rtx_ssrc 123_455
1111

12-
setup do
13-
track = MediaStreamTrack.new(:audio)
14-
15-
codec = %RTPCodecParameters{
16-
payload_type: 111,
17-
mime_type: "audio/opus",
18-
clock_rate: 48_000,
19-
channels: 2,
20-
sdp_fmtp_line: %FMTP{pt: 111, minptime: 10, useinbandfec: true}
12+
@rtp_hdr_exts [%Extmap{id: 1, uri: "urn:ietf:params:rtp-hdrext:sdes:mid"}]
13+
14+
@codec %RTPCodecParameters{
15+
payload_type: 96,
16+
mime_type: "video/VP8",
17+
clock_rate: 90_000
18+
}
19+
20+
@rtx_codec %ExWebRTC.RTPCodecParameters{
21+
payload_type: 124,
22+
mime_type: "video/rtx",
23+
clock_rate: 90_000,
24+
sdp_fmtp_line: %ExSDP.Attribute.FMTP{
25+
pt: 124,
26+
apt: 96
2127
}
28+
}
2229

23-
rtp_hdr_exts = [%Extmap{id: 1, uri: "urn:ietf:params:rtp-hdrext:sdes:mid"}]
30+
setup do
31+
track = MediaStreamTrack.new(:video)
2432

25-
sender = RTPSender.new(track, codec, nil, rtp_hdr_exts, "1", @ssrc, @rtx_ssrc, [])
33+
sender = RTPSender.new(track, @codec, nil, @rtp_hdr_exts, "1", @ssrc, @rtx_ssrc, [])
2634

2735
%{sender: sender}
2836
end
@@ -36,7 +44,7 @@ defmodule ExWebRTC.RTPSenderTest do
3644

3745
assert packet.ssrc == @ssrc
3846
assert packet.marker == false
39-
assert packet.payload_type == 111
47+
assert packet.payload_type == 96
4048
# timestamp and sequence number shouldn't be overwritten
4149
assert packet.timestamp == 0
4250
assert packet.sequence_number == 0
@@ -53,6 +61,66 @@ defmodule ExWebRTC.RTPSenderTest do
5361
assert packet.marker == true
5462
end
5563

64+
describe "get_mline_attrs/1" do
65+
test "without rtx" do
66+
stream_id = MediaStreamTrack.generate_stream_id()
67+
track = MediaStreamTrack.new(:video, [stream_id])
68+
69+
sender = RTPSender.new(track, @codec, nil, @rtp_hdr_exts, "1", @ssrc, @rtx_ssrc, [])
70+
71+
assert [
72+
%ExSDP.Attribute.MSID{id: ^stream_id, app_data: nil},
73+
%ExSDP.Attribute.SSRC{id: @ssrc, attribute: "msid", value: ^stream_id}
74+
] = RTPSender.get_mline_attrs(sender)
75+
end
76+
77+
test "with rtx" do
78+
stream_id = MediaStreamTrack.generate_stream_id()
79+
track = MediaStreamTrack.new(:video, [stream_id])
80+
81+
sender = RTPSender.new(track, @codec, @rtx_codec, @rtp_hdr_exts, "1", @ssrc, @rtx_ssrc, [])
82+
83+
assert [
84+
%ExSDP.Attribute.MSID{id: ^stream_id, app_data: nil},
85+
%ExSDP.Attribute.SSRCGroup{semantics: "FID", ssrcs: [@ssrc, @rtx_ssrc]},
86+
%ExSDP.Attribute.SSRC{id: @ssrc, attribute: "msid", value: ^stream_id},
87+
%ExSDP.Attribute.SSRC{id: @rtx_ssrc, attribute: "msid", value: ^stream_id}
88+
] = RTPSender.get_mline_attrs(sender)
89+
end
90+
91+
test "without media stream" do
92+
track = MediaStreamTrack.new(:video)
93+
94+
sender = RTPSender.new(track, @codec, @rtx_codec, @rtp_hdr_exts, "1", @ssrc, @rtx_ssrc, [])
95+
96+
assert [
97+
%ExSDP.Attribute.MSID{id: "-", app_data: nil},
98+
%ExSDP.Attribute.SSRCGroup{semantics: "FID", ssrcs: [@ssrc, @rtx_ssrc]},
99+
%ExSDP.Attribute.SSRC{id: @ssrc, attribute: "msid", value: "-"},
100+
%ExSDP.Attribute.SSRC{id: @rtx_ssrc, attribute: "msid", value: "-"}
101+
] = RTPSender.get_mline_attrs(sender)
102+
end
103+
104+
test "with multiple media streams" do
105+
s1_id = MediaStreamTrack.generate_stream_id()
106+
s2_id = MediaStreamTrack.generate_stream_id()
107+
108+
track = MediaStreamTrack.new(:video, [s1_id, s2_id])
109+
110+
sender = RTPSender.new(track, @codec, @rtx_codec, @rtp_hdr_exts, "1", @ssrc, @rtx_ssrc, [])
111+
112+
assert [
113+
%ExSDP.Attribute.MSID{id: ^s1_id, app_data: nil},
114+
%ExSDP.Attribute.MSID{id: ^s2_id, app_data: nil},
115+
%ExSDP.Attribute.SSRCGroup{semantics: "FID", ssrcs: [@ssrc, @rtx_ssrc]},
116+
%ExSDP.Attribute.SSRC{id: @ssrc, attribute: "msid", value: ^s1_id},
117+
%ExSDP.Attribute.SSRC{id: @ssrc, attribute: "msid", value: ^s2_id},
118+
%ExSDP.Attribute.SSRC{id: @rtx_ssrc, attribute: "msid", value: ^s1_id},
119+
%ExSDP.Attribute.SSRC{id: @rtx_ssrc, attribute: "msid", value: ^s2_id}
120+
] = RTPSender.get_mline_attrs(sender)
121+
end
122+
end
123+
56124
test "get_stats/2", %{sender: sender} do
57125
timestamp = System.os_time(:millisecond)
58126
payload = <<1, 2, 3>>
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
defmodule ExWebRTC.RTPTransceiverTest do
2+
use ExUnit.Case, async: true
3+
4+
alias ExWebRTC.{MediaStreamTrack, PeerConnection, RTPTransceiver, Utils}
5+
6+
{:ok, pc} = PeerConnection.start_link()
7+
@config PeerConnection.get_configuration(pc)
8+
:ok = PeerConnection.close(pc)
9+
10+
@ssrc 1234
11+
@rtx_ssrc 2345
12+
13+
@track MediaStreamTrack.new(:video, [MediaStreamTrack.generate_stream_id()])
14+
15+
{_key, cert} = ExDTLS.generate_key_cert()
16+
17+
@opts [
18+
ice_ufrag: "ice_ufrag",
19+
ice_pwd: "ice_pwd",
20+
ice_options: "trickle",
21+
fingerprint: {:sha256, Utils.hex_dump(cert)},
22+
setup: :actpass
23+
]
24+
25+
describe "to_offer_mline/1" do
26+
test "with sendrecv direction" do
27+
tr = RTPTransceiver.new(:video, @track, @config, ssrc: @ssrc, rtx_ssrc: @rtx_ssrc)
28+
test_sender_attrs_present(tr)
29+
end
30+
31+
test "with sendonly direction" do
32+
tr =
33+
RTPTransceiver.new(:video, @track, @config,
34+
ssrc: @ssrc,
35+
rtx_ssrc: @rtx_ssrc,
36+
direction: :sendonly
37+
)
38+
39+
test_sender_attrs_present(tr)
40+
end
41+
42+
test "with recvonly direction" do
43+
tr =
44+
RTPTransceiver.new(:video, @track, @config,
45+
ssrc: @ssrc,
46+
rtx_ssrc: @rtx_ssrc,
47+
direction: :recvonly
48+
)
49+
50+
test_sender_attrs_not_present(tr)
51+
end
52+
53+
test "with inactive direction" do
54+
tr =
55+
RTPTransceiver.new(:video, @track, @config,
56+
ssrc: @ssrc,
57+
rtx_ssrc: @rtx_ssrc,
58+
direction: :inactive
59+
)
60+
61+
test_sender_attrs_not_present(tr)
62+
end
63+
end
64+
65+
defp test_sender_attrs_present(tr) do
66+
mline = RTPTransceiver.to_offer_mline(tr, @opts)
67+
68+
# Assert rtp sender attributes are present.
69+
# Their exact values are checked in rtp_sender_test.exs.
70+
assert [%ExSDP.Attribute.MSID{}] = ExSDP.get_attributes(mline, ExSDP.Attribute.MSID)
71+
assert [%ExSDP.Attribute.SSRCGroup{}] = ExSDP.get_attributes(mline, ExSDP.Attribute.SSRCGroup)
72+
73+
assert [%ExSDP.Attribute.SSRC{}, %ExSDP.Attribute.SSRC{}] =
74+
ExSDP.get_attributes(mline, ExSDP.Attribute.SSRC)
75+
end
76+
77+
defp test_sender_attrs_not_present(tr) do
78+
mline = RTPTransceiver.to_offer_mline(tr, @opts)
79+
80+
# assert there are no sender attributes
81+
assert [] == ExSDP.get_attributes(mline, ExSDP.Attribute.MSID)
82+
assert [] == ExSDP.get_attributes(mline, ExSDP.Attribute.SSRCGroup)
83+
assert [] == ExSDP.get_attributes(mline, ExSDP.Attribute.SSRC)
84+
end
85+
end

0 commit comments

Comments
 (0)