@@ -1577,22 +1577,16 @@ func (pc *PeerConnection) startSCTP(maxMessageSize uint32) {
1577
1577
}
1578
1578
}
1579
1579
1580
- //nolint:cyclop
1581
1580
func (pc * PeerConnection ) handleUndeclaredSSRC (
1582
1581
ssrc SSRC ,
1583
- remoteDescription * SessionDescription ,
1582
+ mediaSection * sdp. MediaDescription ,
1584
1583
) (handled bool , err error ) {
1585
- if len (remoteDescription .parsed .MediaDescriptions ) != 1 {
1586
- return false , nil
1587
- }
1588
-
1589
- onlyMediaSection := remoteDescription .parsed .MediaDescriptions [0 ]
1590
1584
streamID := ""
1591
1585
id := ""
1592
1586
hasRidAttribute := false
1593
1587
hasSSRCAttribute := false
1594
1588
1595
- for _ , a := range onlyMediaSection .Attributes {
1589
+ for _ , a := range mediaSection .Attributes {
1596
1590
switch a .Key {
1597
1591
case sdp .AttrKeyMsid :
1598
1592
if split := strings .Split (a .Value , " " ); len (split ) == 2 {
@@ -1609,7 +1603,7 @@ func (pc *PeerConnection) handleUndeclaredSSRC(
1609
1603
if hasRidAttribute {
1610
1604
return false , nil
1611
1605
} else if hasSSRCAttribute {
1612
- return false , errPeerConnSingleMediaSectionHasExplicitSSRC
1606
+ return false , errMediaSectionHasExplictSSRCAttribute
1613
1607
}
1614
1608
1615
1609
incoming := trackDetails {
@@ -1618,7 +1612,7 @@ func (pc *PeerConnection) handleUndeclaredSSRC(
1618
1612
streamID : streamID ,
1619
1613
id : id ,
1620
1614
}
1621
- if onlyMediaSection .MediaName .Media == RTPCodecTypeAudio .String () {
1615
+ if mediaSection .MediaName .Media == RTPCodecTypeAudio .String () {
1622
1616
incoming .kind = RTPCodecTypeAudio
1623
1617
}
1624
1618
@@ -1636,6 +1630,38 @@ func (pc *PeerConnection) handleUndeclaredSSRC(
1636
1630
return true , nil
1637
1631
}
1638
1632
1633
+ // For legacy clients that didn't support urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
1634
+ // or urn:ietf:params:rtp-hdrext:sdes:mid extension, and didn't declare a=ssrc lines.
1635
+ // Assumes that the payload type is unique across the media section.
1636
+ func (pc * PeerConnection ) findMediaSectionByPayloadType (
1637
+ payloadType PayloadType ,
1638
+ remoteDescription * SessionDescription ,
1639
+ ) (selectedMediaSection * sdp.MediaDescription , ok bool ) {
1640
+ for i := range remoteDescription .parsed .MediaDescriptions {
1641
+ descr := remoteDescription .parsed .MediaDescriptions [i ]
1642
+ media := descr .MediaName .Media
1643
+ if ! strings .EqualFold (media , "video" ) && ! strings .EqualFold (media , "audio" ) {
1644
+ continue
1645
+ }
1646
+
1647
+ formats := descr .MediaName .Formats
1648
+ for _ , payloadStr := range formats {
1649
+ payload , err := strconv .ParseUint (payloadStr , 10 , 8 )
1650
+ if err != nil {
1651
+ continue
1652
+ }
1653
+
1654
+ // Return the first media section that has the payload type.
1655
+ // Assuming that the payload type is unique across the media section.
1656
+ if PayloadType (payload ) == payloadType {
1657
+ return remoteDescription .parsed .MediaDescriptions [i ], true
1658
+ }
1659
+ }
1660
+ }
1661
+
1662
+ return nil , false
1663
+ }
1664
+
1639
1665
// Chrome sends probing traffic on SSRC 0. This reads the packets to ensure that we properly
1640
1666
// generate TWCC reports for it. Since this isn't actually media we don't pass this to the user.
1641
1667
func (pc * PeerConnection ) handleNonMediaBandwidthProbe () {
@@ -1665,7 +1691,7 @@ func (pc *PeerConnection) handleNonMediaBandwidthProbe() {
1665
1691
}
1666
1692
}
1667
1693
1668
- func (pc * PeerConnection ) handleIncomingSSRC (rtpStream io.Reader , ssrc SSRC ) error { //nolint:gocognit,cyclop
1694
+ func (pc * PeerConnection ) handleIncomingSSRC (rtpStream io.Reader , ssrc SSRC ) error { //nolint:gocyclo, gocognit,cyclop
1669
1695
remoteDescription := pc .RemoteDescription ()
1670
1696
if remoteDescription == nil {
1671
1697
return errPeerConnRemoteDescriptionNil
@@ -1683,15 +1709,49 @@ func (pc *PeerConnection) handleIncomingSSRC(rtpStream io.Reader, ssrc SSRC) err
1683
1709
}
1684
1710
}
1685
1711
1686
- // If the remote SDP was only one media section the ssrc doesn't have to be explicitly declared
1687
- if handled , err := pc .handleUndeclaredSSRC (ssrc , remoteDescription ); handled || err != nil {
1712
+ // if the SSRC is not declared in the SDP and there is only one media section,
1713
+ // we attempt to resolve it using this single section
1714
+ // This applies even if the client supports RTP extensions:
1715
+ // (urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id and urn:ietf:params:rtp-hdrext:sdes:mid)
1716
+ // and even if the RTP stream contains an incorrect MID or RID.
1717
+ // while this can be incorrect, this is done to maintain compatibility with older behavior.
1718
+ if len (remoteDescription .parsed .MediaDescriptions ) == 1 {
1719
+ mediaSection := remoteDescription .parsed .MediaDescriptions [0 ]
1720
+ if handled , err := pc .handleUndeclaredSSRC (ssrc , mediaSection ); handled || err != nil {
1721
+ return err
1722
+ }
1723
+ }
1724
+
1725
+ // We read the RTP packet to determine the payload type
1726
+ b := make ([]byte , pc .api .settingEngine .getReceiveMTU ())
1727
+
1728
+ i , err := rtpStream .Read (b )
1729
+ if err != nil {
1730
+ return err
1731
+ }
1732
+
1733
+ if i < 4 {
1734
+ return errRTPTooShort
1735
+ }
1736
+
1737
+ payloadType := PayloadType (b [1 ] & 0x7f )
1738
+ params , err := pc .api .mediaEngine .getRTPParametersByPayloadType (payloadType )
1739
+ if err != nil {
1688
1740
return err
1689
1741
}
1690
1742
1691
1743
midExtensionID , audioSupported , videoSupported := pc .api .mediaEngine .getHeaderExtensionID (
1692
1744
RTPHeaderExtensionCapability {sdp .SDESMidURI },
1693
1745
)
1694
1746
if ! audioSupported && ! videoSupported {
1747
+ // try to find media section by payload type as a last resort for legacy clients.
1748
+ mediaSection , ok := pc .findMediaSectionByPayloadType (payloadType , remoteDescription )
1749
+ if ok {
1750
+ if ok , err = pc .handleUndeclaredSSRC (ssrc , mediaSection ); ok || err != nil {
1751
+ return err
1752
+ }
1753
+ }
1754
+
1695
1755
return errPeerConnSimulcastMidRTPExtensionRequired
1696
1756
}
1697
1757
@@ -1706,23 +1766,6 @@ func (pc *PeerConnection) handleIncomingSSRC(rtpStream io.Reader, ssrc SSRC) err
1706
1766
RTPHeaderExtensionCapability {sdp .SDESRepairRTPStreamIDURI },
1707
1767
)
1708
1768
1709
- b := make ([]byte , pc .api .settingEngine .getReceiveMTU ())
1710
-
1711
- i , err := rtpStream .Read (b )
1712
- if err != nil {
1713
- return err
1714
- }
1715
-
1716
- if i < 4 {
1717
- return errRTPTooShort
1718
- }
1719
-
1720
- payloadType := PayloadType (b [1 ] & 0x7f )
1721
- params , err := pc .api .mediaEngine .getRTPParametersByPayloadType (payloadType )
1722
- if err != nil {
1723
- return err
1724
- }
1725
-
1726
1769
streamInfo := createStreamInfo (
1727
1770
"" ,
1728
1771
ssrc ,
0 commit comments