Skip to content

Commit 7f3b1bd

Browse files
authored
Pass all codecs instead of selected one to the rtp_receiver and rtp_sender (#187)
1 parent 6850a28 commit 7f3b1bd

File tree

6 files changed

+64
-47
lines changed

6 files changed

+64
-47
lines changed

lib/ex_webrtc/rtp_receiver.ex

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,9 +61,11 @@ defmodule ExWebRTC.RTPReceiver do
6161
end
6262

6363
@doc false
64-
@spec new(MediaStreamTrack.t(), RTPCodecParameters.t() | nil, [Extmap.t()], [atom()]) ::
65-
receiver()
66-
def new(track, codec, rtp_hdr_exts, features) do
64+
@spec new(MediaStreamTrack.t(), [RTPCodecParameters.t()], [Extmap.t()], [atom()]) :: receiver()
65+
def new(track, codecs, rtp_hdr_exts, features) do
66+
{_rtx_codecs, media_codecs} = Utils.split_rtx_codecs(codecs)
67+
codec = List.first(media_codecs)
68+
6769
# layer `nil` is for the packets without RID/ no simulcast
6870
%{
6971
id: Utils.generate_id(),
@@ -77,8 +79,10 @@ defmodule ExWebRTC.RTPReceiver do
7779
end
7880

7981
@doc false
80-
@spec update(receiver(), RTPCodecParameters.t() | nil, [Extmap.t()], [String.t()]) :: receiver()
81-
def update(receiver, codec, rtp_hdr_exts, stream_ids) do
82+
@spec update(receiver(), [RTPCodecParameters.t()], [Extmap.t()], [String.t()]) :: receiver()
83+
def update(receiver, codecs, rtp_hdr_exts, stream_ids) do
84+
{_rtx_codecs, media_codecs} = Utils.split_rtx_codecs(codecs)
85+
codec = List.first(media_codecs)
8286
simulcast_demuxer = SimulcastDemuxer.update(receiver.simulcast_demuxer, rtp_hdr_exts)
8387
track = %MediaStreamTrack{receiver.track | streams: stream_ids}
8488

lib/ex_webrtc/rtp_sender.ex

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ defmodule ExWebRTC.RTPSender do
1717
id: id(),
1818
track: MediaStreamTrack.t() | nil,
1919
codec: RTPCodecParameters.t() | nil,
20+
codecs: [RTPCodecParameters.t()],
2021
rtp_hdr_exts: %{Extmap.extension_id() => Extmap.t()},
2122
mid: String.t() | nil,
2223
pt: non_neg_integer() | nil,
@@ -67,17 +68,23 @@ defmodule ExWebRTC.RTPSender do
6768
@doc false
6869
@spec new(
6970
MediaStreamTrack.t() | nil,
70-
RTPCodecParameters.t() | nil,
71-
RTPCodecParameters.t() | nil,
71+
[RTPCodecParameters.t()],
7272
[Extmap.t()],
7373
String.t() | nil,
7474
non_neg_integer(),
7575
non_neg_integer(),
7676
[atom()]
7777
) :: sender()
78-
def new(track, codec, rtx_codec, rtp_hdr_exts, mid, ssrc, rtx_ssrc, features) do
78+
def new(track, codecs, rtp_hdr_exts, mid, ssrc, rtx_ssrc, features) do
7979
# convert to a map to be able to find extension id using extension uri
8080
rtp_hdr_exts = Map.new(rtp_hdr_exts, fn extmap -> {extmap.uri, extmap} end)
81+
82+
# We always only take one codec to avoid ambiguity when assigning payload type for RTP packets.
83+
# In other case, if PeerConnection negotiated multiple codecs,
84+
# user would have to pass RTP codec when sending RTP packets,
85+
# or assign payload type on their own.
86+
{codec, rtx_codec} = get_default_codec(codecs)
87+
8188
# TODO: handle cases when codec == nil (no valid codecs after negotiation)
8289
pt = if codec != nil, do: codec.payload_type, else: nil
8390
rtx_pt = if rtx_codec != nil, do: rtx_codec.payload_type, else: nil
@@ -86,6 +93,7 @@ defmodule ExWebRTC.RTPSender do
8693
id: Utils.generate_id(),
8794
track: track,
8895
codec: codec,
96+
codecs: codecs,
8997
rtp_hdr_exts: rtp_hdr_exts,
9098
pt: pt,
9199
rtx_pt: rtx_pt,
@@ -107,11 +115,12 @@ defmodule ExWebRTC.RTPSender do
107115
end
108116

109117
@doc false
110-
@spec update(sender(), String.t(), RTPCodecParameters.t() | nil, RTPCodecParameters.t() | nil, [
111-
Extmap.t()
112-
]) :: sender()
113-
def update(sender, mid, codec, rtx_codec, rtp_hdr_exts) do
118+
@spec update(sender(), String.t(), [RTPCodecParameters.t()], [Extmap.t()]) :: sender()
119+
def update(sender, mid, codecs, rtp_hdr_exts) do
114120
if sender.mid != nil and mid != sender.mid, do: raise(ArgumentError)
121+
122+
{codec, rtx_codec} = get_default_codec(codecs)
123+
115124
# convert to a map to be able to find extension id using extension uri
116125
rtp_hdr_exts = Map.new(rtp_hdr_exts, fn extmap -> {extmap.uri, extmap} end)
117126
# TODO: handle cases when codec == nil (no valid codecs after negotiation)
@@ -127,6 +136,7 @@ defmodule ExWebRTC.RTPSender do
127136
sender
128137
| mid: mid,
129138
codec: codec,
139+
codecs: codecs,
130140
rtp_hdr_exts: rtp_hdr_exts,
131141
pt: pt,
132142
rtx_pt: rtx_pt,
@@ -326,4 +336,20 @@ defmodule ExWebRTC.RTPSender do
326336
pli_count: sender.pli_count
327337
}
328338
end
339+
340+
defp get_default_codec(codecs) do
341+
{rtx_codecs, media_codecs} = Utils.split_rtx_codecs(codecs)
342+
343+
case List.first(media_codecs) do
344+
nil ->
345+
{nil, nil}
346+
347+
codec ->
348+
{codec, find_associated_rtx_codec(rtx_codecs, codec)}
349+
end
350+
end
351+
352+
defp find_associated_rtx_codec(codecs, codec) do
353+
Enum.find(codecs, &(&1.sdp_fmtp_line && &1.sdp_fmtp_line.apt == codec.payload_type))
354+
end
329355
end

lib/ex_webrtc/rtp_transceiver.ex

Lines changed: 6 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -123,12 +123,6 @@ defmodule ExWebRTC.RTPTransceiver do
123123
:video -> {config.video_extensions, config.video_codecs}
124124
end
125125

126-
# When we create sendonly or sendrecv transceiver, we always only take one codec
127-
# to avoid ambiguity when assigning payload type for RTP packets in RTPSender.
128-
# In other case, if PeerConnection negotiated multiple codecs,
129-
# user would have to pass RTP codec when sending RTP packets,
130-
# or assign payload type on their own.
131-
{codec, codec_rtx} = get_default_codec(codecs)
132126
track = MediaStreamTrack.new(kind)
133127

134128
id = Utils.generate_id()
@@ -141,13 +135,12 @@ defmodule ExWebRTC.RTPTransceiver do
141135
send(self(), {:send_nacks, id})
142136
end
143137

144-
receiver = RTPReceiver.new(track, codec, header_extensions, config.features)
138+
receiver = RTPReceiver.new(track, codecs, header_extensions, config.features)
145139

146140
sender =
147141
RTPSender.new(
148142
sender_track,
149-
codec,
150-
codec_rtx,
143+
codecs,
151144
header_extensions,
152145
nil,
153146
options[:ssrc],
@@ -196,7 +189,6 @@ defmodule ExWebRTC.RTPTransceiver do
196189
{:mid, mid} = ExSDP.get_attribute(mline, :mid)
197190

198191
track = MediaStreamTrack.from_mline(mline)
199-
{codec, codec_rtx} = get_default_codec(codecs)
200192

201193
id = Utils.generate_id()
202194

@@ -208,13 +200,12 @@ defmodule ExWebRTC.RTPTransceiver do
208200
send(self(), {:send_nacks, id})
209201
end
210202

211-
receiver = RTPReceiver.new(track, codec, header_extensions, config.features)
203+
receiver = RTPReceiver.new(track, codecs, header_extensions, config.features)
212204

213205
sender =
214206
RTPSender.new(
215207
nil,
216-
codec,
217-
codec_rtx,
208+
codecs,
218209
header_extensions,
219210
mid,
220211
ssrc,
@@ -265,11 +256,10 @@ defmodule ExWebRTC.RTPTransceiver do
265256

266257
codecs = Configuration.intersect_codecs(config, mline)
267258
header_extensions = Configuration.intersect_extensions(config, mline)
268-
{codec, codec_rtx} = get_default_codec(codecs)
269259
stream_ids = SDPUtils.get_stream_ids(mline)
270260

271-
receiver = RTPReceiver.update(transceiver.receiver, codec, header_extensions, stream_ids)
272-
sender = RTPSender.update(transceiver.sender, mid, codec, codec_rtx, header_extensions)
261+
receiver = RTPReceiver.update(transceiver.receiver, codecs, header_extensions, stream_ids)
262+
sender = RTPSender.update(transceiver.sender, mid, codecs, header_extensions)
273263

274264
%{
275265
transceiver
@@ -600,17 +590,4 @@ defmodule ExWebRTC.RTPTransceiver do
600590
factor = :rand.uniform() + 0.5
601591
trunc(factor * @report_interval)
602592
end
603-
604-
defp get_default_codec(codecs) do
605-
{rtxs, codecs} = Enum.split_with(codecs, &String.ends_with?(&1.mime_type, "/rtx"))
606-
607-
case List.first(codecs) do
608-
nil ->
609-
{nil, nil}
610-
611-
codec ->
612-
rtx = Enum.find(rtxs, &(&1.sdp_fmtp_line.apt == codec.payload_type))
613-
{codec, rtx}
614-
end
615-
end
616593
end

lib/ex_webrtc/utils.ex

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
defmodule ExWebRTC.Utils do
22
@moduledoc false
3+
alias ExWebRTC.RTPCodecParameters
34

45
@spec hex_dump(binary()) :: String.t()
56
def hex_dump(binary) do
@@ -17,4 +18,10 @@ defmodule ExWebRTC.Utils do
1718
@spec to_int(boolean()) :: 0 | 1
1819
def to_int(false), do: 0
1920
def to_int(true), do: 1
21+
22+
@spec split_rtx_codecs([RTPCodecParameters.t()]) ::
23+
{[RTPCodecParameters.t()], [RTPCodecParameters.t()]}
24+
def split_rtx_codecs(codecs) do
25+
Enum.split_with(codecs, &String.ends_with?(&1.mime_type, "/rtx"))
26+
end
2027
end

test/ex_webrtc/rtp_receiver_test.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ defmodule ExWebRTC.RTPReceiverTest do
1111
payload = <<1, 2, 3>>
1212

1313
track = MediaStreamTrack.new(:audio)
14-
receiver = RTPReceiver.new(track, @codec, [], [])
14+
receiver = RTPReceiver.new(track, [@codec], [], [])
1515

1616
assert [] == RTPReceiver.get_stats(receiver, timestamp)
1717

test/ex_webrtc/rtp_sender_test.exs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ defmodule ExWebRTC.RTPSenderTest do
3030
setup do
3131
track = MediaStreamTrack.new(:video)
3232

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

3535
%{sender: sender}
3636
end
@@ -66,7 +66,7 @@ defmodule ExWebRTC.RTPSenderTest do
6666
stream_id = MediaStreamTrack.generate_stream_id()
6767
track = MediaStreamTrack.new(:video, [stream_id])
6868

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

7171
assert [
7272
%ExSDP.Attribute.MSID{id: ^stream_id, app_data: nil},
@@ -78,7 +78,8 @@ defmodule ExWebRTC.RTPSenderTest do
7878
stream_id = MediaStreamTrack.generate_stream_id()
7979
track = MediaStreamTrack.new(:video, [stream_id])
8080

81-
sender = RTPSender.new(track, @codec, @rtx_codec, @rtp_hdr_exts, "1", @ssrc, @rtx_ssrc, [])
81+
sender =
82+
RTPSender.new(track, [@codec, @rtx_codec], @rtp_hdr_exts, "1", @ssrc, @rtx_ssrc, [])
8283

8384
assert [
8485
%ExSDP.Attribute.MSID{id: ^stream_id, app_data: nil},
@@ -91,7 +92,8 @@ defmodule ExWebRTC.RTPSenderTest do
9192
test "without media stream" do
9293
track = MediaStreamTrack.new(:video)
9394

94-
sender = RTPSender.new(track, @codec, @rtx_codec, @rtp_hdr_exts, "1", @ssrc, @rtx_ssrc, [])
95+
sender =
96+
RTPSender.new(track, [@codec, @rtx_codec], @rtp_hdr_exts, "1", @ssrc, @rtx_ssrc, [])
9597

9698
assert [
9799
%ExSDP.Attribute.MSID{id: "-", app_data: nil},
@@ -107,7 +109,8 @@ defmodule ExWebRTC.RTPSenderTest do
107109

108110
track = MediaStreamTrack.new(:video, [s1_id, s2_id])
109111

110-
sender = RTPSender.new(track, @codec, @rtx_codec, @rtp_hdr_exts, "1", @ssrc, @rtx_ssrc, [])
112+
sender =
113+
RTPSender.new(track, [@codec, @rtx_codec], @rtp_hdr_exts, "1", @ssrc, @rtx_ssrc, [])
111114

112115
assert [
113116
%ExSDP.Attribute.MSID{id: ^s1_id, app_data: nil},

0 commit comments

Comments
 (0)