diff --git a/mediaengine.go b/mediaengine.go index bdab6b9fb60..281652303e3 100644 --- a/mediaengine.go +++ b/mediaengine.go @@ -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"): m.negotiatedVideo = true typ = RTPCodecTypeVideo default: @@ -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}) } } diff --git a/peerconnection.go b/peerconnection.go index 1794e8d41ef..f4687649773 100644 --- a/peerconnection.go +++ b/peerconnection.go @@ -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) + } + case direction == RTPTransceiverDirectionRecvonly: if t.Direction() == RTPTransceiverDirectionSendrecv { t.setDirection(RTPTransceiverDirectionSendonly) @@ -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 } go func(track *TrackRemote) { diff --git a/rtptransceiver.go b/rtptransceiver.go index 4ff4ead7d64..06bc0178778 100644 --- a/rtptransceiver.go +++ b/rtptransceiver.go @@ -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 @@ -80,6 +81,33 @@ func (t *RTPTransceiver) getCodecs() []RTPCodecParameters { return filteredCodecs } +// SetHeaderExtensions stores header extension from SDP +func (t *RTPTransceiver) SetHeaderExtensions(headerExtensions []RTPHeaderExtensionParameter) error { + 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 + } + + 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 { diff --git a/sdp.go b/sdp.go index c181bfe606d..a982493aa33 100644 --- a/sdp.go +++ b/sdp.go @@ -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 @@ -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