Skip to content

Commit 6d46f50

Browse files
committed
Fix RC between publishers with duplicated id
1 parent 4a4e50f commit 6d46f50

File tree

2 files changed

+84
-5
lines changed

2 files changed

+84
-5
lines changed

lib/live_ex_webrtc/player.ex

Lines changed: 72 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ defmodule LiveExWebRTC.Player do
8080

8181
@type t() :: struct()
8282

83+
@check_lock_timeout_ms 3000
84+
@max_lock_timeout 3000
85+
8386
defstruct id: nil,
8487
publisher_id: nil,
8588
publisher_audio_track: nil,
@@ -101,7 +104,10 @@ defmodule LiveExWebRTC.Player do
101104
target_layer: nil,
102105
video_layers: [],
103106
# codec that will be used for video sending
104-
video_send_codec: nil
107+
video_send_codec: nil,
108+
last_seen: nil,
109+
locked: nil,
110+
lock_timer: nil
105111

106112
alias ExWebRTC.{ICECandidate, MediaStreamTrack, PeerConnection, RTP.Munger, SessionDescription}
107113
alias ExRTCP.Packet.PayloadFeedback.PLI
@@ -317,16 +323,34 @@ defmodule LiveExWebRTC.Player do
317323
publisher_audio_track: ^publisher_audio_track,
318324
publisher_video_track: ^publisher_video_track
319325
} ->
320-
# tracks are the same, do nothing
326+
# tracks are the same, update last_seen and do nothing
327+
player = %Player{player | last_seen: System.monotonic_time(:millisecond)}
328+
socket = assign(socket, player: player)
329+
{:noreply, socket}
330+
331+
%Player{locked: true} ->
332+
# Different tracks but we are still receiving updates from old publisher. Ignore.
321333
{:noreply, socket}
322334

323335
%Player{
324336
publisher_audio_track: old_publisher_audio_track,
325337
publisher_video_track: old_publisher_video_track,
326-
video_layers: old_layers
338+
video_layers: old_layers,
339+
locked: false
327340
} ->
328341
if player.pc, do: PeerConnection.close(player.pc)
329342

343+
if player.lock_timer do
344+
Process.cancel_timer(player.lock_timer)
345+
346+
# flush mailbox
347+
receive do
348+
:check_lock -> :ok
349+
after
350+
0 -> :ok
351+
end
352+
end
353+
330354
video_layers = (publisher_video_track && publisher_video_track.rids) || ["h"]
331355

332356
video_layers =
@@ -344,7 +368,10 @@ defmodule LiveExWebRTC.Player do
344368
layer: "h",
345369
target_layer: "h",
346370
video_layers: video_layers,
347-
munger: nil
371+
munger: nil,
372+
last_seen: System.monotonic_time(:millisecond),
373+
locked: true,
374+
lock_timer: Process.send_after(self(), :check_lock, @check_lock_timeout_ms)
348375
}
349376

350377
socket = assign(socket, :player, player)
@@ -372,6 +399,25 @@ defmodule LiveExWebRTC.Player do
372399
end
373400
end
374401

402+
@impl true
403+
def handle_info({:live_ex_webrtc, :bye, publisher_audio_track, publisher_video_track}, socket) do
404+
%{player: player} = socket.assigns
405+
406+
case player do
407+
%Player{
408+
publisher_audio_track: ^publisher_audio_track,
409+
publisher_video_track: ^publisher_video_track
410+
} ->
411+
player = %Player{player | locked: false}
412+
socket = assign(socket, player: player)
413+
{:noreply, socket}
414+
415+
_ ->
416+
{:noreply, socket}
417+
end
418+
end
419+
420+
@impl true
375421
def handle_info({:live_ex_webrtc, :audio, packet}, socket) do
376422
%{player: player} = socket.assigns
377423

@@ -384,6 +430,7 @@ defmodule LiveExWebRTC.Player do
384430
{:noreply, socket}
385431
end
386432

433+
@impl true
387434
def handle_info({:live_ex_webrtc, :video, rid, packet}, socket) do
388435
%{player: player} = socket.assigns
389436

@@ -427,6 +474,27 @@ defmodule LiveExWebRTC.Player do
427474
end
428475
end
429476

477+
@impl true
478+
def handle_info(:check_lock, %{assigns: %{locked: true}} = socket) do
479+
now = System.monotonic_time(:millisecond)
480+
481+
if now - socket.assigns.last_seen > @max_lock_timeout do
482+
# unlock i.e. allow for track update
483+
socket = assign(socket, lock_timer: nil, locked: false)
484+
{:noreply, socket}
485+
else
486+
timer = Process.send_after(self(), :check_lock, @check_lock_timeout_ms)
487+
socket = assign(socket, :lock_timer, timer)
488+
{:noreply, socket}
489+
end
490+
end
491+
492+
@impl true
493+
def handle_info(:check_lock, socket) do
494+
socket = assign(socket, :lock_timer, nil)
495+
{:noreply, socket}
496+
end
497+
430498
@impl true
431499
def handle_event("toggle-settings", _params, socket) do
432500
socket =

lib/live_ex_webrtc/publisher.ex

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ defmodule LiveExWebRTC.Publisher do
2525
`{:live_ex_webrtc, :audio, ExRTP.Packet.t()}`. Packets for non-simulcast video tracks are always
2626
sent with "h" identifier.
2727
* `streams:info:#{publisher.id}"` - for receiving information about publisher tracks and their layers.
28-
The message is in form of: `{:live_ex_webrtc, :info, audio_track :: ExWebRTC.MediaStreamTrack.t(), video_track :: ExWebRTC.MediaStreamTrack.t()}`.
28+
The message is in form of: `{:live_ex_webrtc, :info | :bye, audio_track :: ExWebRTC.MediaStreamTrack.t(), video_track :: ExWebRTC.MediaStreamTrack.t()}`.
2929
* `publishers:#{publisher_id}` for sending keyframe request.
3030
The message must be in form of `{:live_ex_webrtc, :keyframe_req, "l" | "m" | "h"}`
3131
E.g.
@@ -731,6 +731,17 @@ defmodule LiveExWebRTC.Publisher do
731731
end
732732
end
733733

734+
@impl true
735+
def terminate(_reason, socket) do
736+
%{publisher: publisher} = socket.assigns
737+
738+
PubSub.broadcast(
739+
publisher.pubsub,
740+
"streams:info:#{publisher.id}",
741+
{:live_ex_webrtc, :bye, publisher.audio_track, publisher.video_track}
742+
)
743+
end
744+
734745
defp spawn_peer_connection(socket) do
735746
%{publisher: publisher} = socket.assigns
736747

0 commit comments

Comments
 (0)