mirror of
https://github.com/pion/webrtc.git
synced 2025-12-24 11:51:03 +08:00
Match codec order of remote peer
Done when creating a transceiver from remote description to respect codec order preference of remote peer. There was a recent change to include partial matches which overwrote same codecs and also rtx was getting magled. Change it by removing codecs from search space as matches are found so that a codec match is applied only once. Also, move RTX matching to separate block to ensure proper RTXes ar matched.
This commit is contained in:
committed by
Raja Subramanian
parent
42b3cfd2ca
commit
c376d0edf9
@@ -8,10 +8,13 @@ package webrtc
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/pion/rtp"
|
||||
"github.com/pion/sdp/v3"
|
||||
"github.com/pion/webrtc/v4/internal/fmtp"
|
||||
)
|
||||
|
||||
// RTPTransceiver represents a combination of an RTPSender and an RTPReceiver that share a common mid.
|
||||
@@ -73,7 +76,7 @@ func (t *RTPTransceiver) getCodecs() []RTPCodecParameters {
|
||||
|
||||
mediaEngineCodecs := t.api.mediaEngine.getCodecsByKind(t.kind)
|
||||
if len(t.codecs) == 0 {
|
||||
return mediaEngineCodecs
|
||||
return filterUnattachedRTX(mediaEngineCodecs)
|
||||
}
|
||||
|
||||
filteredCodecs := []RTPCodecParameters{}
|
||||
@@ -90,6 +93,96 @@ func (t *RTPTransceiver) getCodecs() []RTPCodecParameters {
|
||||
return filterUnattachedRTX(filteredCodecs)
|
||||
}
|
||||
|
||||
// match codecs from remote description, used when remote is offerer and creating a transceiver
|
||||
// from remote description with the aim of keeping order of codecs in remote description.
|
||||
func (t *RTPTransceiver) setCodecPreferencesFromRemoteDescription(media *sdp.MediaDescription) { //nolint:cyclop
|
||||
remoteCodecs, err := codecsFromMediaDescription(media)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// make a copy as this slice is modified
|
||||
leftCodecs := append([]RTPCodecParameters{}, t.api.mediaEngine.getCodecsByKind(t.kind)...)
|
||||
|
||||
// find codec matches between what is in remote description and
|
||||
// the transceivers codecs and use payload type registered to
|
||||
// media engine.
|
||||
payloadMapping := make(map[PayloadType]PayloadType) // for RTX re-mapping later
|
||||
filterByMatchType := func(matchFilter codecMatchType) []RTPCodecParameters {
|
||||
filteredCodecs := []RTPCodecParameters{}
|
||||
for remoteCodecIdx := len(remoteCodecs) - 1; remoteCodecIdx >= 0; remoteCodecIdx-- {
|
||||
remoteCodec := remoteCodecs[remoteCodecIdx]
|
||||
if strings.EqualFold(remoteCodec.RTPCodecCapability.MimeType, MimeTypeRTX) {
|
||||
continue
|
||||
}
|
||||
|
||||
matchCodec, matchType := codecParametersFuzzySearch(
|
||||
remoteCodec,
|
||||
leftCodecs,
|
||||
)
|
||||
if matchType == matchFilter {
|
||||
payloadMapping[remoteCodec.PayloadType] = matchCodec.PayloadType
|
||||
|
||||
remoteCodec.PayloadType = matchCodec.PayloadType
|
||||
filteredCodecs = append([]RTPCodecParameters{remoteCodec}, filteredCodecs...)
|
||||
|
||||
// removed matched codec for next round
|
||||
remoteCodecs = append(remoteCodecs[:remoteCodecIdx], remoteCodecs[remoteCodecIdx+1:]...)
|
||||
|
||||
needleFmtp := fmtp.Parse(
|
||||
matchCodec.RTPCodecCapability.MimeType,
|
||||
matchCodec.RTPCodecCapability.ClockRate,
|
||||
matchCodec.RTPCodecCapability.Channels,
|
||||
matchCodec.RTPCodecCapability.SDPFmtpLine,
|
||||
)
|
||||
|
||||
for leftCodecIdx := len(leftCodecs) - 1; leftCodecIdx >= 0; leftCodecIdx-- {
|
||||
leftCodec := leftCodecs[leftCodecIdx]
|
||||
leftCodecFmtp := fmtp.Parse(
|
||||
leftCodec.RTPCodecCapability.MimeType,
|
||||
leftCodec.RTPCodecCapability.ClockRate,
|
||||
leftCodec.RTPCodecCapability.Channels,
|
||||
leftCodec.RTPCodecCapability.SDPFmtpLine,
|
||||
)
|
||||
|
||||
if needleFmtp.Match(leftCodecFmtp) {
|
||||
leftCodecs = append(leftCodecs[:leftCodecIdx], leftCodecs[leftCodecIdx+1:]...)
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return filteredCodecs
|
||||
}
|
||||
|
||||
filteredCodecs := filterByMatchType(codecMatchExact)
|
||||
filteredCodecs = append(filteredCodecs, filterByMatchType(codecMatchPartial)...)
|
||||
|
||||
// find RTX associations and add those
|
||||
for remotePayloadType, mediaEnginePayloadType := range payloadMapping {
|
||||
remoteRTX := findRTXPayloadType(remotePayloadType, remoteCodecs)
|
||||
if remoteRTX == PayloadType(0) {
|
||||
continue
|
||||
}
|
||||
|
||||
mediaEngineRTX := findRTXPayloadType(mediaEnginePayloadType, leftCodecs)
|
||||
if mediaEngineRTX == PayloadType(0) {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, rtxCodec := range leftCodecs {
|
||||
if rtxCodec.PayloadType == mediaEngineRTX {
|
||||
filteredCodecs = append(filteredCodecs, rtxCodec)
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
_ = t.SetCodecPreferences(filteredCodecs)
|
||||
}
|
||||
|
||||
// Sender returns the RTPTransceiver's RTPSender if it has one.
|
||||
func (t *RTPTransceiver) Sender() *RTPSender {
|
||||
if v, ok := t.sender.Load().(*RTPSender); ok {
|
||||
|
||||
Reference in New Issue
Block a user