diff --git a/examples/example.exs b/examples/example.exs index cf39b7ac..39265717 100644 --- a/examples/example.exs +++ b/examples/example.exs @@ -32,7 +32,7 @@ defmodule Peer do {:ok, pc} = PeerConnection.start_link(ice_servers: @ice_servers) - {:ok, %{conn: conn, stream: stream, peer_connection: pc, other_mid: nil}} + {:ok, %{conn: conn, stream: stream, peer_connection: pc, track_id: nil}} other -> Logger.error("Couldn't connect to the signalling server: #{inspect(other)}") @@ -97,9 +97,7 @@ defmodule Peer do msg = %{"type" => "offer", "sdp" => offer.sdp} :gun.ws_send(state.conn, state.stream, {:text, Jason.encode!(msg)}) - [_, %RTPTransceiver{mid: mid}] = PeerConnection.get_transceivers(pc) - - %{state | other_mid: mid} + %{state | track_id: track.id} end defp handle_ws_message(%{"type" => "answer", "sdp" => sdp}, state) do @@ -141,13 +139,13 @@ defmodule Peer do :gun.ws_send(state.conn, state.stream, {:text, Jason.encode!(msg)}) end - defp handle_webrtc_message({:rtp, _mid, _packet}, %{other_mid: nil}) do + defp handle_webrtc_message({:rtp, _mid, _packet}, %{track_id: nil}) do Logger.warning("Received RTP, but out transceiver has not beed created") end defp handle_webrtc_message({:rtp, _mid, packet}, state) do Logger.info("Received RTP: #{inspect(packet)}") - PeerConnection.send_rtp(state.peer_connection, state.other_mid, packet) + PeerConnection.send_rtp(state.peer_connection, state.track_id, packet) end defp handle_webrtc_message(msg, _state) do diff --git a/lib/ex_webrtc/dtls_transport.ex b/lib/ex_webrtc/dtls_transport.ex index 04968e7e..077eaaf6 100644 --- a/lib/ex_webrtc/dtls_transport.ex +++ b/lib/ex_webrtc/dtls_transport.ex @@ -172,6 +172,7 @@ defmodule ExWebRTC.DTLSTransport do end defp handle_ice({:data, <> = data}, state) when f in 20..64 do + # TODO: handle {:connection_closed, _} case ExDTLS.handle_data(state.dtls, data) do {:handshake_packets, packets, timeout} when state.ice_state in [:connected, :completed] -> :ok = ICEAgent.send_data(state.ice_agent, packets) diff --git a/lib/ex_webrtc/peer_connection.ex b/lib/ex_webrtc/peer_connection.ex index 64d5508b..9dac60d0 100644 --- a/lib/ex_webrtc/peer_connection.ex +++ b/lib/ex_webrtc/peer_connection.ex @@ -114,8 +114,8 @@ defmodule ExWebRTC.PeerConnection do end @spec send_rtp(peer_connection(), String.t(), ExRTP.Packet.t()) :: :ok - def send_rtp(peer_connection, mid, packet) do - GenServer.cast(peer_connection, {:send_rtp, mid, packet}) + def send_rtp(peer_connection, track_id, packet) do + GenServer.cast(peer_connection, {:send_rtp, track_id, packet}) end #### CALLBACKS #### @@ -332,22 +332,37 @@ defmodule ExWebRTC.PeerConnection do end @impl true - def handle_cast({:send_rtp, mid, packet}, state) do - # TODO: this is very temporary - id = + def handle_cast({:send_rtp, track_id, packet}, state) do + sdes_id = Enum.find_value(state.demuxer.extensions, fn {ext_id, {ExRTP.Packet.Extension.SourceDescription, :mid}} -> ext_id _ -> nil end) - mid_ext = - %ExRTP.Packet.Extension.SourceDescription{text: mid} - |> ExRTP.Packet.Extension.SourceDescription.to_raw(id) + # TODO: iterating over transceivers is not optimal + # but this is, most likely, going to be refactored anyways + maybe_transceiver = + Enum.find(state.transceivers, fn + %{sender: %{track: %{id: id}}} -> id == track_id + _ -> false + end) - packet - |> ExRTP.Packet.set_extension(:two_byte, [mid_ext]) - |> ExRTP.Packet.encode() - |> then(&DTLSTransport.send_rtp(state.dtls_transport, &1)) + case maybe_transceiver do + %RTPTransceiver{mid: mid} -> + mid_ext = + %ExRTP.Packet.Extension.SourceDescription{text: mid} + |> ExRTP.Packet.Extension.SourceDescription.to_raw(sdes_id) + + packet + |> ExRTP.Packet.set_extension(:two_byte, [mid_ext]) + |> ExRTP.Packet.encode() + |> then(&DTLSTransport.send_rtp(state.dtls_transport, &1)) + + nil -> + Logger.warning( + "Attempted to send packet to track with unrecognized id: #{inspect(track_id)}" + ) + end {:noreply, state} end @@ -373,10 +388,15 @@ defmodule ExWebRTC.PeerConnection do @impl true def handle_info({:rtp, data}, state) do - case Demuxer.demux(state.demuxer, data) do - {:ok, demuxer, mid, packet} -> - notify(state.owner, {:rtp, mid, packet}) - {:noreply, %__MODULE__{state | demuxer: demuxer}} + with {:ok, demuxer, mid, packet} <- Demuxer.demux(state.demuxer, data), + %RTPTransceiver{} = t <- Enum.find(state.transceivers, &(&1.mid == mid)) do + track_id = t.receiver.track.id + notify(state.owner, {:rtp, track_id, packet}) + {:noreply, %__MODULE__{state | demuxer: demuxer}} + else + nil -> + Logger.warning("Received RTP with unrecognized MID: #{inspect(data)}") + {:noreply, state} {:error, reason} -> Logger.error("Unable to demux RTP, reason: #{inspect(reason)}") @@ -458,7 +478,7 @@ defmodule ExWebRTC.PeerConnection do RTPTransceiver.find_by_mid(state.transceivers, tr.mid) == nil and tr.direction in [:recvonly, :sendrecv] end) - |> Enum.map(fn tr -> MediaStreamTrack.new(tr.kind) end) + |> Enum.map(fn tr -> tr.receiver.track end) for track <- new_remote_tracks do notify(state.owner, {:track, track}) diff --git a/lib/ex_webrtc/rtp_transceiver.ex b/lib/ex_webrtc/rtp_transceiver.ex index da012589..e8397c37 100644 --- a/lib/ex_webrtc/rtp_transceiver.ex +++ b/lib/ex_webrtc/rtp_transceiver.ex @@ -20,8 +20,8 @@ defmodule ExWebRTC.RTPTransceiver do kind: kind(), rtp_hdr_exts: [ExSDP.Attribute.Extmap.t()], codecs: [RTPCodecParameters.t()], - receiver: nil, - sender: nil + receiver: RTPReceiver.t(), + sender: RTPSender.t() } @enforce_keys [:mid, :direction, :kind]