ExWebRTC.PeerConnection (ex_webrtc v0.8.1)

View Source

Implementation of the RTCPeerConnection.

Summary

Types

Possible connection states.

Possible ICE connection states.

Possible ICE gathering states.

Messages sent by the ExWebRTC.PeerConnection process to its controlling process.

Possible signaling states.

Functions

Adds a new remote ICE candidate.

Returns a specification to start this module under a supervisor.

Closes the PeerConnection.

Closes a DataChannel identified by ref.

Changes the controlling process of this peer_connection process.

Creates an SDP answer.

Returns a list of all running ExWebRTC.PeerConnection processes.

Returns current peer_connection configuration.

Returns the connection state.

Returns the current local description.

Returns the current remote description.

Returns t:ExWebRTC.DataChannel.t() identified by channel_ref if it exists, nil otherwise.

Returns the ICE connection state.

Returns the ICE gathering state.

Returns the local description.

Returns the pending local description.

Returns the pending remote description.

Returns the remote description.

Returns the signaling state.

Returns PeerConnection's statistics.

Returns the list of transceivers.

Removes the track assigned to the sender specified by the sender_id.

Replaces the track assigned to the sender specified by the sender_id.

Sends data over DataChannel, using channel identified by ref.

Sends an RTCP PLI feedback to the remote peer using the track specified by the track_id.

Sends an RTP packet to the remote peer using the track specified by the track_id.

Sets very simple packet loss.

Sets the codec that will be used for sending RTP packets.

Sets the direction of transceiver specified by the transceiver_id.

Stops the transceiver specified by the transceiver_id.

Types

connection_state()

@type connection_state() ::
  :new | :connecting | :connected | :disconnected | :failed | :closed

Possible connection states.

For the exact meaning, refer to the RTCPeerConnection: connectionState property.

ice_connection_state()

@type ice_connection_state() ::
  :new | :checking | :connected | :completed | :failed | :disconnected | :closed

Possible ICE connection states.

For the exact meaning, refer to the RTCPeerConnection: iceConnectionState property.

ice_gathering_state()

@type ice_gathering_state() :: :new | :gathering | :complete

Possible ICE gathering states.

For the exact meaning, refer to the RTCPeerConnection: iceGatheringState property.

message()

@type message() ::
  {:ex_webrtc, pid(),
   {:connection_state_change, connection_state()}
   | {:ice_candidate, ExWebRTC.ICECandidate.t()}
   | {:ice_connection_state_change, ice_connection_state()}
   | {:ice_gathering_state_change, ice_gathering_state()}
   | :negotiation_needed
   | {:signaling_state_change, signaling_state()}
   | {:data_channel_state_change, ExWebRTC.DataChannel.ref(),
      ExWebRTC.DataChannel.ready_state()}
   | {:data_channel, ExWebRTC.DataChannel.t()}
   | {:track, ExWebRTC.MediaStreamTrack.t()}
   | {:track_muted, ExWebRTC.MediaStreamTrack.id()}
   | {:track_ended, ExWebRTC.MediaStreamTrack.id()}
   | {:data, ExWebRTC.DataChannel.ref(), binary()}
   | {:rtp, ExWebRTC.MediaStreamTrack.id(), String.t() | nil, ExRTP.Packet.t()}}
  | {:rtcp, [{ExWebRTC.MediaStreamTrack.id() | nil, ExRTCP.Packet.packet()}]}

Messages sent by the ExWebRTC.PeerConnection process to its controlling process.

Most of the messages match the RTCPeerConnection events, except for:

  • :track_muted, :track_ended - these match the MediaStreamTrack events.
  • :data - data received from DataChannel identified by its ref.
  • :rtp and :rtcp - these contain packets received by the PeerConnection. The third element of :rtp tuple is a simulcast RID and is set to nil if simulcast is not used.
  • each of the packets in :rtcp message is in the form of {track_id, packet} tuple, where track_id is the id of the corrsponding track. In case of PLI and NACK, this is the id of an outgoing (sender's) track id, in case of Sender and Receiver Reports - incoming (receiver's) track id. If matching to a track was not possible (like in the case of TWCC packedts), track_id is set to nil.

peer_connection()

@type peer_connection() :: GenServer.server()

signaling_state()

@type signaling_state() :: :stable | :have_local_offer | :have_remote_offer

Possible signaling states.

For the exact meaning, refer to the RTCPeerConnection: signalingState property.

Functions

add_ice_candidate(peer_connection, candidate)

@spec add_ice_candidate(peer_connection(), ExWebRTC.ICECandidate.t()) ::
  :ok | {:error, term()}

Adds a new remote ICE candidate.

For more information, refer to the RTCPeerConnection: addIceCandidate() method.

add_track(peer_connection, track)

Adds a new track.

For more information, refer to the RTCPeerConnection: addTrack() method.

add_transceiver(peer_connection, kind_or_track, options \\ [])

Adds a new transceiver.

For more information, refer to the RTCPeerConnection: addTransceiver() method.

child_spec(init_arg)

Returns a specification to start this module under a supervisor.

See Supervisor.

close(peer_connection)

@spec close(peer_connection()) :: :ok

Closes the PeerConnection.

This function kills the peer_connection process. For more information, refer to the RTCPeerConnection: close() method.

close_data_channel(peer_connection, channel_ref)

@spec close_data_channel(peer_connection(), ExWebRTC.DataChannel.ref()) :: :ok

Closes a DataChannel identified by ref.

As of now, the closed channel directly transitions to closed state, which is signaled with {:data_channel_state_change, ref, :closed} message. For more information, refer to the RTCDataChannel: close() method.

If ref does not identify any DataChannel, this function behaves like no-op.

controlling_process(peer_connection, controlling_process)

@spec controlling_process(peer_connection(), Process.dest()) :: :ok

Changes the controlling process of this peer_connection process.

Controlling process is a process that receives all of the messages (described by message/0) from this PeerConnection.

create_answer(peer_connection)

@spec create_answer(peer_connection()) ::
  {:ok, ExWebRTC.SessionDescription.t()} | {:error, term()}

Creates an SDP answer.

For more information, refer to the RTCPeerConnection: createAnswer() method.

create_data_channel(peer_connection, label, opts \\ [])

@spec create_data_channel(
  peer_connection(),
  String.t(),
  ExWebRTC.DataChannel.options()
) ::
  {:ok, ExWebRTC.DataChannel.t()} | {:error, atom()}

Creates a new DataChannel.

For more information, refer to the RTCPeerConnection: createDataChannel() method.

create_offer(peer_connection, options \\ [])

@spec create_offer(peer_connection(), [{:restart_ice?, boolean()}]) ::
  {:ok, ExWebRTC.SessionDescription.t()} | {:error, term()}

Creates an SDP offer.

For more information, refer to the RTCPeerConnection: createOffer() method.

get_all_running()

@spec get_all_running() :: [pid()]

Returns a list of all running ExWebRTC.PeerConnection processes.

get_configuration(peer_connection)

Returns current peer_connection configuration.

Note: the configuration may change after applying remote description.

get_connection_state(peer_connection)

@spec get_connection_state(peer_connection()) :: connection_state()

Returns the connection state.

For more information, refer to the RTCPeerConnection: connectionState property.

get_current_local_description(peer_connection)

@spec get_current_local_description(peer_connection()) ::
  ExWebRTC.SessionDescription.t() | nil

Returns the current local description.

For more information, refer to the RTCPeerConnection: currentLocalDescription property.

get_current_remote_description(peer_connection)

@spec get_current_remote_description(peer_connection()) ::
  ExWebRTC.SessionDescription.t() | nil

Returns the current remote description.

For more information, refer to the RTCPeerConnection: currentRemoteDescription property.

get_data_channel(peer_connection, channel_ref)

@spec get_data_channel(peer_connection(), ExWebRTC.DataChannel.ref()) ::
  ExWebRTC.DataChannel.t() | nil

Returns t:ExWebRTC.DataChannel.t() identified by channel_ref if it exists, nil otherwise.

This function can be especially helpful when you want to obtain DataChannel id. Normally, before SCTP connection is established, create_data_channel/3 will return DataChannel struct with id set to nil. After receiving {:data_channel_state_change, ref, :open} message, you can call this function to obtain the same struct, but with id set to proper value.

get_ice_connection_state(peer_connection)

@spec get_ice_connection_state(peer_connection()) :: ice_connection_state()

Returns the ICE connection state.

For more information, refer to the RTCPeerConnection: iceConnectionState property.

get_ice_gathering_state(peer_connection)

@spec get_ice_gathering_state(peer_connection()) :: ice_gathering_state()

Returns the ICE gathering state.

For more information, refer to the RTCPeerConnection: iceGatheringState property.

get_local_description(peer_connection)

@spec get_local_description(peer_connection()) ::
  ExWebRTC.SessionDescription.t() | nil

Returns the local description.

For more information, refer to the RTCPeerConnection: localDescription property.

get_pending_local_description(peer_connection)

@spec get_pending_local_description(peer_connection()) ::
  ExWebRTC.SessionDescription.t() | nil

Returns the pending local description.

For more information, refer to the RTCPeerConnection: pendingLocalDescription property.

get_pending_remote_description(peer_connection)

@spec get_pending_remote_description(peer_connection()) ::
  ExWebRTC.SessionDescription.t() | nil

Returns the pending remote description.

For more information, refer to the RTCPeerConnection: pendingRemoteDescription property.

get_remote_description(peer_connection)

@spec get_remote_description(peer_connection()) ::
  ExWebRTC.SessionDescription.t() | nil

Returns the remote description.

For more information, refer to the RTCPeerConnection: remoteDescription property.

get_signaling_state(peer_connection)

@spec get_signaling_state(peer_connection()) :: signaling_state()

Returns the signaling state.

For more information, refer to the RTCPeerConnection: signalingState property.

get_stats(peer_connection)

@spec get_stats(peer_connection()) :: %{required(atom() | integer()) => map()}

Returns PeerConnection's statistics.

For more information, refer to the RTCPeerConnection: getStats() method. See RTCStatsReport for the output structure.

get_transceivers(peer_connection)

@spec get_transceivers(peer_connection()) :: [ExWebRTC.RTPTransceiver.t()]

Returns the list of transceivers.

For more information, refer to the RTCPeerConnection: getTransceivers() method.

remove_track(peer_connection, sender_id)

@spec remove_track(peer_connection(), ExWebRTC.RTPSender.id()) ::
  :ok | {:error, term()}

Removes the track assigned to the sender specified by the sender_id.

For more information, refer to the RTCPeerConnection: removeTrack() method.

replace_track(peer_connection, sender_id, track)

@spec replace_track(
  peer_connection(),
  ExWebRTC.RTPSender.id(),
  ExWebRTC.MediaStreamTrack.t()
) ::
  :ok | {:error, term()}

Replaces the track assigned to the sender specified by the sender_id.

For more information, refer to the RTCRtpSender: replaceTrack() method.

send_data(peer_connection, channel_ref, data)

@spec send_data(peer_connection(), ExWebRTC.DataChannel.ref(), binary()) :: :ok

Sends data over DataChannel, using channel identified by ref.

Requires the channel to be in :open state.

If ref does not identify any DataChannel, this function behaves like no-op.

send_pli(peer_connection, track_id, rid \\ nil)

@spec send_pli(peer_connection(), ExWebRTC.MediaStreamTrack.id(), String.t() | nil) ::
  :ok

Sends an RTCP PLI feedback to the remote peer using the track specified by the track_id.

Set rid to the simulcast rid for which the PLI should be sent. If simulcast is not used, rid should be equal to nil.

send_rtp(peer_connection, track_id, packet, opts \\ [])

@spec send_rtp(
  peer_connection(),
  ExWebRTC.MediaStreamTrack.id(),
  ExRTP.Packet.t(),
  [{:rtx?, boolean()}]
) :: :ok

Sends an RTP packet to the remote peer using the track specified by the track_id.

The following fields of the RTP packet will be overwritten by this function:

  • payload type
  • ssrc
  • rtp header extensions

If you negotiated multiple codecs (hence payload types) and you want to choose, which one should be used, see set_sender_codec/3.

Options:

  • rtx? - send the packet as if it was retransmitted (use SSRC and payload type specific to RTX)

set_local_description(peer_connection, description)

@spec set_local_description(peer_connection(), ExWebRTC.SessionDescription.t()) ::
  :ok | {:error, term()}

Sets the local description.

For more information, refer to the RTCPeerConnection: setLocalDescription() method.

set_packet_loss(peer_connection, value)

@spec set_packet_loss(peer_connection(), 0..100) :: :ok

Sets very simple packet loss.

Can be used for experimental purposes.

set_remote_description(peer_connection, description)

@spec set_remote_description(peer_connection(), ExWebRTC.SessionDescription.t()) ::
  :ok | {:error, term()}

Sets the remote description.

For more information, refer to the RTCPeerConnection: setRemoteDescription() method.

set_sender_codec(peer_connection, sender_id, codec)

@spec set_sender_codec(
  peer_connection(),
  ExWebRTC.RTPSender.id(),
  ExWebRTC.RTPCodecParameters.t()
) ::
  :ok | {:error, term()}

Sets the codec that will be used for sending RTP packets.

send_rtp/4 overrides some of the RTP packet fields. In particular, when multiple codecs are negotiated, send_rtp/4 will use payload type of the most preffered by the remote side codec (i.e. the first one from the list of codecs in the remote description).

Use this function if you want to select, which codec (hence payload type) should be used for sending.

Once the first RTP packet is sent (via send_rtp/4), set_sender_codec/3 can only be called with a codec with the same clock rate.

Although very unlikely, keep in mind that after renegotiation, the selected codec may no longer be supported by the remote side and you might need to call this function again, passing a new codec.

To check available codecs you can use get_transceivers/1:

{:ok, pc} = PeerConnection.start_link()
{:ok, rtp_sender} = PeerConnection.add_track(MediaStreamTrack.new(:video))

# exchange SDP with the remote side
# {:ok, offer} = PeerConnection.create_offer(pc)
# ...

tr =
  pc
  |> PeerConnection.get_transceivers()
  |> Enum.find(fn tr -> tr.sender.id == rtp_sender.id end)

dbg(tr.codecs) # list of supported codecs both for sending and receiving

# e.g. always prefer h264 over vp8
h264 = Enum.find(tr.codecs, fn codec -> codec.mime_type == "video/H264" end)
vp8 = Enum.find(tr.codecs, fn codec -> codec.mime_type == "video/VP8" end)

:ok = PeerConnection.set_sender_codec(pc, rtp_sender.id, h264 || vp8)

This function can only be called once the first negotiation passes.

set_transceiver_direction(peer_connection, transceiver_id, direction)

@spec set_transceiver_direction(
  peer_connection(),
  ExWebRTC.RTPTransceiver.id(),
  ExWebRTC.RTPTransceiver.direction()
) :: :ok | {:error, term()}

Sets the direction of transceiver specified by the transceiver_id.

For more information, refer to the RTCRtpTransceiver: direction property.

start(pc_opts \\ [], gen_server_opts \\ [])

Starts a new ExWebRTC.PeerConnection process.

ExWebRTC.PeerConnection is a GenServer under the hood, thus this function allows for passing the generic GenServer.options/0 as an argument.

start_link(pc_opts \\ [], gen_server_opts \\ [])

Starts a new ExWebRTC.PeerConnection process.

Works identically to start/2, but links to the calling process.

stop_transceiver(peer_connection, transceiver_id)

@spec stop_transceiver(peer_connection(), ExWebRTC.RTPTransceiver.id()) ::
  :ok | {:error, term()}

Stops the transceiver specified by the transceiver_id.

For more information, refer to the RTCRtpTransceiver: stop() method.