@@ -9,7 +9,8 @@ defmodule Membrane.WebRTC.ExWebRTCSource do
99 alias Membrane.WebRTC . { ExWebRTCUtils , SignalingChannel , SimpleWebSocketServer , WhipServer }
1010
1111 def_options signaling: [ ] ,
12- video_codec: [ ] ,
12+ allowed_video_codecs: [ ] ,
13+ preferred_video_codec: [ ] ,
1314 ice_servers: [ ] ,
1415 keyframe_interval: [ ] ,
1516 sdp_candidates_timeout: [ ]
@@ -39,6 +40,8 @@ defmodule Membrane.WebRTC.ExWebRTCSource do
3940 status: :init | :connecting | :connected | :closed ,
4041 audio_params: [ ExWebRTC.RTPCodecParameters . t ( ) ] ,
4142 video_params: [ ExWebRTC.RTPCodecParameters . t ( ) ] ,
43+ allowed_video_codecs: [ :h264 | :vp8 ] ,
44+ preferred_video_codec: :h264 | :vp8 ,
4245 ice_servers: [ ExWebRTC.PeerConnection.Configuration . ice_server ( ) ] ,
4346 keyframe_interval: Membrane.Time . t ( ) | nil ,
4447 sdp_candidates_timeout: Membrane.Time . t ( ) | nil
@@ -47,13 +50,16 @@ defmodule Membrane.WebRTC.ExWebRTCSource do
4750 @ enforce_keys [
4851 :signaling ,
4952 :audio_params ,
50- :video_params ,
53+ :allowed_video_codecs ,
54+ :preferred_video_codec ,
5155 :ice_servers ,
5256 :keyframe_interval ,
5357 :sdp_candidates_timeout
5458 ]
59+
5560 defstruct @ enforce_keys ++
5661 [
62+ video_params: nil ,
5763 pc: nil ,
5864 output_tracks: % { } ,
5965 awaiting_outputs: [ ] ,
@@ -69,7 +75,8 @@ defmodule Membrane.WebRTC.ExWebRTCSource do
6975 % State {
7076 signaling: opts . signaling ,
7177 audio_params: ExWebRTCUtils . codec_params ( :opus ) ,
72- video_params: ExWebRTCUtils . codec_params ( opts . video_codec ) ,
78+ allowed_video_codecs: opts . allowed_video_codecs |> Enum . uniq ( ) ,
79+ preferred_video_codec: opts . preferred_video_codec ,
7380 ice_servers: opts . ice_servers ,
7481 keyframe_interval: opts . keyframe_interval ,
7582 sdp_candidates_timeout: opts . sdp_candidates_timeout
@@ -95,18 +102,10 @@ defmodule Membrane.WebRTC.ExWebRTCSource do
95102
96103 @ impl true
97104 def handle_playing ( _ctx , state ) do
98- { :ok , pc } =
99- PeerConnection . start (
100- ice_servers: state . ice_servers ,
101- video_codecs: state . video_params ,
102- audio_codecs: state . audio_params
103- )
104-
105- Process . monitor ( pc )
106105 Process . monitor ( state . signaling . pid )
107106 SignalingChannel . register_element ( state . signaling )
108107
109- { [ ] , % { state | pc: pc , status: :connecting } }
108+ { [ ] , % { state | status: :connecting } }
110109 end
111110
112111 @ impl true
@@ -216,6 +215,8 @@ defmodule Membrane.WebRTC.ExWebRTCSource do
216215 state
217216 ) do
218217 Membrane.Logger . debug ( "Received SDP offer" )
218+
219+ { codecs_notification , state } = ensure_peer_connection_started ( sdp , state )
219220 :ok = PeerConnection . set_remote_description ( state . pc , sdp )
220221
221222 { new_tracks , awaiting_outputs } =
@@ -264,7 +265,7 @@ defmodule Membrane.WebRTC.ExWebRTCSource do
264265 [ ]
265266 end )
266267
267- { tracks_notification ++ stream_formats , state }
268+ { codecs_notification ++ tracks_notification ++ stream_formats , state }
268269 end
269270
270271 @ impl true
@@ -303,6 +304,35 @@ defmodule Membrane.WebRTC.ExWebRTCSource do
303304 { [ ] , state }
304305 end
305306
307+ defp ensure_peer_connection_started ( sdp , % { pc: nil } = state ) do
308+ video_codecs_in_sdp = ExWebRTCUtils . get_video_codecs_from_sdp ( sdp )
309+
310+ negotiated_video_codecs =
311+ state . allowed_video_codecs
312+ |> Enum . filter ( & ( & 1 in video_codecs_in_sdp ) )
313+ |> case do
314+ [ ] -> [ ]
315+ [ codec ] -> [ codec ]
316+ _both -> [ state . preferred_video_codec ]
317+ end
318+
319+ video_params = ExWebRTCUtils . codec_params ( negotiated_video_codecs )
320+
321+ { :ok , pc } =
322+ PeerConnection . start (
323+ ice_servers: state . ice_servers ,
324+ video_codecs: video_params ,
325+ audio_codecs: state . audio_params
326+ )
327+
328+ Process . monitor ( pc )
329+
330+ notify_parent = [ notify_parent: { :negotiated_video_codecs , negotiated_video_codecs } ]
331+ { notify_parent , % { state | pc: pc , video_params: video_params } }
332+ end
333+
334+ defp ensure_peer_connection_started ( _sdp , state ) , do: { [ ] , state }
335+
306336 defp maybe_answer ( state ) do
307337 if Enum . all? ( state . output_tracks , fn { _id , % { status: status } } -> status == :connected end ) do
308338 % { pc: pc } = state
0 commit comments