Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Firefox case when screen and camera offer together #2107

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
30 changes: 18 additions & 12 deletions mediaengine.go
Expand Up @@ -476,10 +476,10 @@ func (m *MediaEngine) updateFromRemoteDescription(desc sdp.SessionDescription) e
for _, media := range desc.MediaDescriptions {
var typ RTPCodecType
switch {
case !m.negotiatedAudio && strings.EqualFold(media.MediaName.Media, "audio"):
case strings.EqualFold(media.MediaName.Media, "audio"):
m.negotiatedAudio = true
typ = RTPCodecTypeAudio
case !m.negotiatedVideo && strings.EqualFold(media.MediaName.Media, "video"):
case strings.EqualFold(media.MediaName.Media, "video"):
Copy link
Contributor Author

@boks1971 boks1971 Jan 31, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is for point 1 in the PR commit notes. More than one media description of the same kind was getting ignored.

m.negotiatedVideo = true
typ = RTPCodecTypeVideo
default:
Expand Down Expand Up @@ -561,18 +561,24 @@ func (m *MediaEngine) getRTPParametersByKind(typ RTPCodecType, directions []RTPT

m.mu.RLock()
defer m.mu.RUnlock()
if m.negotiatedVideo && typ == RTPCodecTypeVideo ||
m.negotiatedAudio && typ == RTPCodecTypeAudio {
for id, e := range m.negotiatedHeaderExtensions {
if haveRTPTransceiverDirectionIntersection(e.allowedDirections, directions) && (e.isAudio && typ == RTPCodecTypeAudio || e.isVideo && typ == RTPCodecTypeVideo) {
headerExtensions = append(headerExtensions, RTPHeaderExtensionParameter{ID: id, URI: e.uri})
}
}

var mediaHeaderExtensions map[int]mediaEngineHeaderExtension
if (m.negotiatedVideo && typ == RTPCodecTypeVideo) || (m.negotiatedAudio && typ == RTPCodecTypeAudio) {
mediaHeaderExtensions = m.negotiatedHeaderExtensions
} else {
mediaHeaderExtensions = make(map[int]mediaEngineHeaderExtension, len(m.headerExtensions))
for id, e := range m.headerExtensions {
if haveRTPTransceiverDirectionIntersection(e.allowedDirections, directions) && (e.isAudio && typ == RTPCodecTypeAudio || e.isVideo && typ == RTPCodecTypeVideo) {
headerExtensions = append(headerExtensions, RTPHeaderExtensionParameter{ID: id + 1, URI: e.uri})
}
mediaHeaderExtensions[id+1] = e
}
}

for id, e := range mediaHeaderExtensions {
if (typ == RTPCodecTypeVideo && !e.isVideo) || (typ == RTPCodecTypeAudio && !e.isAudio) {
continue
}

if haveRTPTransceiverDirectionIntersection(e.allowedDirections, directions) {
headerExtensions = append(headerExtensions, RTPHeaderExtensionParameter{ID: id, URI: e.uri})
Sean-Der marked this conversation as resolved.
Show resolved Hide resolved
}
}

Expand Down
10 changes: 9 additions & 1 deletion peerconnection.go
Expand Up @@ -1091,6 +1091,14 @@ func (pc *PeerConnection) SetRemoteDescription(desc SessionDescription) error {
_ = t.SetCodecPreferences(filteredCodecs)
}

if extensions, err := rtpExtensionsFromMediaDescription(media); err == nil {
headerExtensions := []RTPHeaderExtensionParameter{}
for uri, id := range extensions {
headerExtensions = append(headerExtensions, RTPHeaderExtensionParameter{URI: uri, ID: id})
}
_ = t.SetHeaderExtensions(headerExtensions)
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Storing the extension from SDP media description in the transceiver.

case direction == RTPTransceiverDirectionRecvonly:
if t.Direction() == RTPTransceiverDirectionSendrecv {
t.setDirection(RTPTransceiverDirectionSendonly)
Expand Down Expand Up @@ -1203,7 +1211,7 @@ func (pc *PeerConnection) startReceiver(incoming trackDetails, receiver *RTPRece

for _, t := range receiver.Tracks() {
if t.SSRC() == 0 || t.RID() != "" {
return
continue
Sean-Der marked this conversation as resolved.
Show resolved Hide resolved
}

go func(track *TrackRemote) {
Expand Down
30 changes: 29 additions & 1 deletion rtptransceiver.go
Expand Up @@ -18,7 +18,8 @@ type RTPTransceiver struct {
receiver atomic.Value // *RTPReceiver
direction atomic.Value // RTPTransceiverDirection

codecs []RTPCodecParameters // User provided codecs via SetCodecPreferences
codecs []RTPCodecParameters // User provided codecs via SetCodecPreferences
headerExtensions []RTPHeaderExtensionParameter

stopped bool
kind RTPCodecType
Expand Down Expand Up @@ -80,6 +81,33 @@ func (t *RTPTransceiver) getCodecs() []RTPCodecParameters {
return filteredCodecs
}

// SetHeaderExtensions stores header extension from SDP
func (t *RTPTransceiver) SetHeaderExtensions(headerExtensions []RTPHeaderExtensionParameter) error {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be ok if we did RTPSender.SetParameters

I don't see this exposed on the receiver side. Still looking

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went with parallel to SetCodecPreferences which is on the transceiver now. I think it could be in the transceiver as sender and receiver on a transceiver should use the same codec/header extensions.

t.mu.Lock()
defer t.mu.Unlock()

t.headerExtensions = headerExtensions
return nil
}

func (t *RTPTransceiver) hasHeaderExtension(uri string) bool {
t.mu.RLock()
defer t.mu.RUnlock()

// if nothing specific set, accept all
if len(t.headerExtensions) == 0 {
return true
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Had to add this accept all case to fix a test. But, I think this is fine to keep the old behaviour.


for _, he := range t.headerExtensions {
if he.URI == uri {
return true
}
}

return false
}

// Sender returns the RTPTransceiver's RTPSender if it has one
func (t *RTPTransceiver) Sender() *RTPSender {
if v := t.sender.Load(); v != nil {
Expand Down
17 changes: 16 additions & 1 deletion sdp.go
Expand Up @@ -340,7 +340,18 @@ func populateLocalCandidates(sessionDescription *SessionDescription, i *ICEGathe
}
}

func addTransceiverSDP(d *sdp.SessionDescription, isPlanB, shouldAddCandidates bool, dtlsFingerprints []DTLSFingerprint, mediaEngine *MediaEngine, midValue string, iceParams ICEParameters, candidates []ICECandidate, dtlsRole sdp.ConnectionRole, iceGatheringState ICEGatheringState, mediaSection mediaSection) (bool, error) {
func addTransceiverSDP(
d *sdp.SessionDescription,
isPlanB, shouldAddCandidates bool,
dtlsFingerprints []DTLSFingerprint,
mediaEngine *MediaEngine,
midValue string,
iceParams ICEParameters,
candidates []ICECandidate,
dtlsRole sdp.ConnectionRole,
iceGatheringState ICEGatheringState,
mediaSection mediaSection,
) (bool, error) {
transceivers := mediaSection.transceivers
if len(transceivers) < 1 {
return false, errSDPZeroTransceivers
Expand Down Expand Up @@ -392,6 +403,10 @@ func addTransceiverSDP(d *sdp.SessionDescription, isPlanB, shouldAddCandidates b

parameters := mediaEngine.getRTPParametersByKind(t.kind, directions)
for _, rtpExtension := range parameters.HeaderExtensions {
if !t.hasHeaderExtension(rtpExtension.URI) {
continue
}

extURL, err := url.Parse(rtpExtension.URI)
if err != nil {
return false, err
Expand Down