diff --git a/lib/ex_webrtc/peer_connection.ex b/lib/ex_webrtc/peer_connection.ex index 9cc47277..a80d421b 100644 --- a/lib/ex_webrtc/peer_connection.ex +++ b/lib/ex_webrtc/peer_connection.ex @@ -2417,6 +2417,9 @@ defmodule ExWebRTC.PeerConnection do # https://www.w3.org/TR/webrtc/#dfn-check-if-negotiation-is-needed defp tr_negotiation_needed?([], _), do: false + defp tr_negotiation_needed?([tr | _transceivers], _state) when tr.stopping and not tr.stopped, + do: true + defp tr_negotiation_needed?([tr | _transceivers], _state) when tr.mid == nil, do: true defp tr_negotiation_needed?([tr | transceivers], state) do diff --git a/lib/ex_webrtc/rtp_transceiver.ex b/lib/ex_webrtc/rtp_transceiver.ex index 08fc1fc6..f7a26819 100644 --- a/lib/ex_webrtc/rtp_transceiver.ex +++ b/lib/ex_webrtc/rtp_transceiver.ex @@ -434,7 +434,11 @@ defmodule ExWebRTC.RTPTransceiver do mline = to_mline(transceiver, opts) %ExSDP.Media{mline | port: 0} - transceiver.stopping == true or transceiver.stopped == true -> + transceiver.stopping == true -> + opts = Keyword.put(opts, :direction, :inactive) + to_mline(transceiver, opts) + + transceiver.stopped == true -> opts = Keyword.put(opts, :direction, :inactive) mline = to_mline(transceiver, opts) %ExSDP.Media{mline | port: 0} diff --git a/test/ex_webrtc/peer_connection_test.exs b/test/ex_webrtc/peer_connection_test.exs index 39fdfc78..ff33bf4a 100644 --- a/test/ex_webrtc/peer_connection_test.exs +++ b/test/ex_webrtc/peer_connection_test.exs @@ -651,6 +651,59 @@ defmodule ExWebRTC.PeerConnectionTest do assert sdp.media == [] end + test "after remote offer" do + {:ok, pc1} = PeerConnection.start_link() + {:ok, pc2} = PeerConnection.start_link() + + PeerConnection.add_transceiver(pc1, :video) + {:ok, offer} = PeerConnection.create_offer(pc1) + :ok = PeerConnection.set_local_description(pc1, offer) + + :ok = PeerConnection.set_remote_description(pc2, offer) + [tr] = PeerConnection.get_transceivers(pc2) + :ok = PeerConnection.stop_transceiver(pc2, tr.id) + + assert [ + %RTPTransceiver{ + current_direction: nil, + direction: :inactive, + stopping: true, + stopped: false + } + ] = PeerConnection.get_transceivers(pc2) + + {:ok, answer} = PeerConnection.create_answer(pc2) + [video] = ExSDP.parse!(answer.sdp).media + assert video.port == 9 + + :ok = PeerConnection.set_local_description(pc2, answer) + :ok = PeerConnection.set_remote_description(pc1, answer) + + assert_receive {:ex_webrtc, ^pc2, :negotiation_needed} + + # Ensure transceiver is removed after renegotiation + + {:ok, offer2} = PeerConnection.create_offer(pc2) + :ok = PeerConnection.set_local_description(pc2, offer2) + [new_video] = ExSDP.parse!(offer2.sdp).media + assert new_video.port == 0 + + assert [ + %RTPTransceiver{ + current_direction: :inactive, + direction: :inactive, + stopping: true, + stopped: false + } + ] = PeerConnection.get_transceivers(pc2) + + :ok = PeerConnection.set_remote_description(pc1, offer2) + {:ok, answer2} = PeerConnection.create_answer(pc1) + + :ok = PeerConnection.set_remote_description(pc2, answer2) + assert [] = PeerConnection.get_transceivers(pc2) + end + test "with renegotiation" do {:ok, pc1} = PeerConnection.start_link() {:ok, pc2} = PeerConnection.start_link()