Skip to content

Commit

Permalink
Enable renegotation
Browse files Browse the repository at this point in the history
No "perfect renegotiation" because that's too new and unsupported by
browsers. Instead, a workaround by deferring adding the own offer:
https://stackoverflow.com/questions/65059808/downward-compatibility-of-webrtc-renegotiation
  • Loading branch information
farao committed Dec 29, 2020
1 parent f0774ad commit 53f8557
Show file tree
Hide file tree
Showing 7 changed files with 209 additions and 40 deletions.
32 changes: 31 additions & 1 deletion coffee/gum.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@ palava = @palava
class palava.Gum extends @EventEmitter
constructor: (config) ->
@config = config || { video: true, audio: true }
@stream = null
@stream = null # this stream switches from localStream to displayStream on request
@localStream = null
@displayStream = null

changeConfig: (config) =>
@config = config
Expand All @@ -17,16 +19,44 @@ class palava.Gum extends @EventEmitter
@config
).then(
(stream) =>
@localStream = stream.clone()
@stream = stream
@emit 'stream_ready', stream
).catch(
(error) =>
@emit 'stream_error', error
)

requestDisplaySharing: =>
navigator.mediaDevices.getDisplayMedia(
{video:true}
).then(
(stream) =>
# add audio track to the display stream (if any)
if @localStream.getAudioTracks().length > 0
stream.addTrack(@localStream.getAudioTracks()[0], @localStream)
@displayStream = stream.clone()
@stream = stream
@emit 'display_stream_ready', stream
).catch(
(error) =>
@emit 'display_stream_error', error
)

stopDisplaySharing: =>
@stream = @localStream
@emit 'display_stream_stop', @displayStream
@displayStream = null

getStream: =>
@stream

getLocalStream: =>
@localStream

getDisplayStream: =>
@displayStream

releaseStream: =>
if @stream
@stream.getAudioTracks().forEach( (track) => track.stop() )
Expand Down
7 changes: 7 additions & 0 deletions coffee/local_peer.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@ class palava.LocalPeer extends palava.Peer
@emit 'stream_ready', e
@userMedia.on 'stream_error', (e) =>
@emit 'stream_error', e
@userMedia.on 'display_stream_ready', (e) =>
@emit 'display_stream_ready', e
@userMedia.on 'display_stream_error', (e) =>
@emit 'display_stream_error', e
if @getStream()
@ready = true
@emit 'stream_ready'
Expand All @@ -54,6 +58,9 @@ class palava.LocalPeer extends palava.Peer
getStream: =>
@userMedia.getStream()

requestDisplaySharing: =>
@userMedia.requestDisplaySharing()

# Updates the status of the local peer. The status is extended or updated with the given items.
#
# @param status [Object] Object containing the new items
Expand Down
85 changes: 59 additions & 26 deletions coffee/remote_peer.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,14 @@ class palava.RemotePeer extends palava.Peer

@dataChannels = {}

@offers = offers
@makingOffer = false
@ignoreOffer = false
@setRemoteAnswerPending = false

@setupRoom()
@setupPeerConnection(offers)
@setupDistributor()

@setupPeerConnection(offers)
if offers
@sendOffer()

Expand Down Expand Up @@ -62,8 +66,7 @@ class palava.RemotePeer extends palava.Peer
credential: @turnCredentials.password
{iceServers: options}

# Sets up the peer connection and its events
#
# Sets up the peer connection and its events #
# @nodoc
#
setupPeerConnection: (offers) =>
Expand All @@ -87,6 +90,9 @@ class palava.RemotePeer extends palava.Peer
@ready = false
@emit 'stream_removed'

@peerConnection.onnegotiationneeded = () =>
@sendOffer()

@peerConnection.oniceconnectionstatechange = (event) =>
connectionState = event.target.iceConnectionState

Expand All @@ -107,12 +113,33 @@ class palava.RemotePeer extends palava.Peer
@error = "connection_closed"
@emit 'connection_closed'

# TODO onsignalingstatechange

if @room.localPeer.getStream()
@peerConnection.addStream @room.localPeer.getStream()
else
# not suppored yet
for track in @room.localPeer.getStream().getTracks()
@peerConnection.addTrack(track, @room.localPeer.getStream())

@room.localPeer.on 'display_stream_ready', (stream) =>
videoSender = @peerConnection.getSenders().find(
(sender) => sender.track.kind == "video"
)
if videoSender
# if there is a local video track then replace it because that's faster
# and does not need renegotiation
videoSender.replaceTrack(track)
else
@peerConnection.addTrack(stream.getVideoTracks()[0],
@room.localPeer.getStream())

@room.localPeer.on 'display_stream_stop', (stream) =>
localVideoTracks = @room.localPeer.getLocalStream().getVideoTracks()
if localVideoTracks.length > 0
# if there was a local video track then reuse the display video track
# because it's faster and does not need renegotiation
videoSender = @peerConnection.getSenders().find(
(sender) => sender.track.kind == "video"
)
videoSender.replaceTrack(localVideoTracks[0])
else
@peerConnection.removeTrack(stream.getVideoTracks()[0])

# data channel setup

Expand Down Expand Up @@ -140,8 +167,6 @@ class palava.RemotePeer extends palava.Peer
# @nodoc
#
setupDistributor: =>
# TODO _ in events also in rtc-server
# TODO consistent protocol naming
@distributor = new palava.Distributor(@room.channel, @id)

@distributor.on 'peer_left', (msg) =>
Expand All @@ -157,16 +182,22 @@ class palava.RemotePeer extends palava.Peer
return if msg.candidate == ""
candidate = new RTCIceCandidate({candidate: msg.candidate, sdpMLineIndex: msg.sdpmlineindex, sdpMid: msg.sdpmid})
unless @room.options.filterIceCandidateTypes.includes(candidate.type)
@peerConnection.addIceCandidate(candidate)
await @peerConnection.addIceCandidate(candidate)

@distributor.on 'offer', (msg) =>
@peerConnection.setRemoteDescription(new RTCSessionDescription(msg.sdp))
@emit 'offer' # ignored so far
# we sent an offer already and are the preferred offerer, so we don't back down
return if @pendingOffer && @offers

# we backed down, so we drop the pending offer and choose the other peer's offer
@pendingOffer = null

await @peerConnection.setRemoteDescription(new RTCSessionDescription(msg.sdp))
@sendAnswer()

@distributor.on 'answer', (msg) =>
@peerConnection.setRemoteDescription(new RTCSessionDescription(msg.sdp))
@emit 'answer' # ignored so far
await @peerConnection.setLocalDescription(@pendingOffer) if @pendingOffer
@pendingOffer = null
await @peerConnection.setRemoteDescription(new RTCSessionDescription(msg.sdp))

@distributor.on 'peer_updated_status', (msg) =>
@status = msg.status
Expand Down Expand Up @@ -199,30 +230,32 @@ class palava.RemotePeer extends palava.Peer
@on 'oaerror', (e) => @room.emit('peer_oaerror', @, e)
@on 'channel_ready', (n, c) => @room.emit('peer_channel_ready', @, n, c)

# Sends the offer for a peer connection
#
# @nodoc
sendMessage: (data) =>
@distributor.send
event: 'message'
data: data

# Sends the offer to create a peer connection
#
sendOffer: =>
@peerConnection.createOffer @sdpSender('offer'), @oaError, palava.browser.getConstraints()
@peerConnection.createOffer @sdpSender('offer'), @oaError, palava.browser.getConstraints() if @peerConnection.signalingState == "stable" && !@pendingOffer

# Sends the answer to create a peer connection
#
sendAnswer: =>
@peerConnection.createAnswer @sdpSender('answer'), @oaError, palava.browser.getConstraints()

sendMessage: (data) =>
@distributor.send
event: 'message'
data: data

# Helper for sending sdp
# Send offer/answer
#
# @nodoc
#
sdpSender: (event) =>
(sdp) =>
@peerConnection.setLocalDescription(sdp)
if event == 'offer'
@pendingOffer = sdp
else
await @peerConnection.setLocalDescription(sdp)
@distributor.send
event: event
sdp: sdp
Expand Down
1 change: 1 addition & 0 deletions coffee/room.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ class palava.Room extends @EventEmitter

@options.ownStatus[key] = status[key] for key in status
@options.ownStatus.user_agent ||= palava.browser.getUserAgent()
@options.ownStatus.user_agent_version ||= palava.browser.getUserAgentVersion()

@distributor.send
event: 'join_room'
Expand Down
2 changes: 1 addition & 1 deletion palava.bundle.js

Large diffs are not rendered by default.

Loading

0 comments on commit 53f8557

Please sign in to comment.