diff --git a/peerconnection.go b/peerconnection.go index 379be7b9b2f..c7c92f99fb5 100644 --- a/peerconnection.go +++ b/peerconnection.go @@ -1588,7 +1588,7 @@ func (pc *PeerConnection) handleIncomingSSRC(rtpStream io.Reader, ssrc SSRC) err } var mid, rid, rsid string - payloadType, err := handleUnknownRTPPacket(b[:i], uint8(midExtensionID), uint8(streamIDExtensionID), uint8(repairStreamIDExtensionID), &mid, &rid, &rsid) + payloadType, paddingOnly, err := handleUnknownRTPPacket(b[:i], uint8(midExtensionID), uint8(streamIDExtensionID), uint8(repairStreamIDExtensionID), &mid, &rid, &rsid) if err != nil { return err } @@ -1606,12 +1606,17 @@ func (pc *PeerConnection) handleIncomingSSRC(rtpStream io.Reader, ssrc SSRC) err for readCount := 0; readCount <= simulcastProbeCount; readCount++ { if mid == "" || (rid == "" && rsid == "") { + // skip padding only packets for probing + if paddingOnly { + readCount-- + } + i, _, err := interceptor.Read(b, nil) if err != nil { return err } - if _, err = handleUnknownRTPPacket(b[:i], uint8(midExtensionID), uint8(streamIDExtensionID), uint8(repairStreamIDExtensionID), &mid, &rid, &rsid); err != nil { + if _, paddingOnly, err = handleUnknownRTPPacket(b[:i], uint8(midExtensionID), uint8(streamIDExtensionID), uint8(repairStreamIDExtensionID), &mid, &rid, &rsid); err != nil { return err } diff --git a/peerconnection_media_test.go b/peerconnection_media_test.go index b5b740a3629..044c7c21eda 100644 --- a/peerconnection_media_test.go +++ b/peerconnection_media_test.go @@ -1280,7 +1280,28 @@ func TestPeerConnection_Simulcast(t *testing.T) { assert.NoError(t, signalPair(pcOffer, pcAnswer)) - for sequenceNumber := uint16(0); !ridsFullfilled(); sequenceNumber++ { + // padding only packets should not affect simulcast probe + var sequenceNumber uint16 + for sequenceNumber = 0; sequenceNumber < simulcastProbeCount+10; sequenceNumber++ { + time.Sleep(20 * time.Millisecond) + + for _, track := range []*TrackLocalStaticRTP{vp8WriterA, vp8WriterB, vp8WriterC} { + pkt := &rtp.Packet{ + Header: rtp.Header{ + Version: 2, + SequenceNumber: sequenceNumber, + PayloadType: 96, + Padding: true, + }, + Payload: []byte{0x00, 0x02}, + } + + assert.NoError(t, track.WriteRTP(pkt)) + } + } + assert.False(t, ridsFullfilled(), "Simulcast probe should not be fulfilled by padding only packets") + + for ; !ridsFullfilled(); sequenceNumber++ { time.Sleep(20 * time.Millisecond) for _, track := range []*TrackLocalStaticRTP{vp8WriterA, vp8WriterB, vp8WriterC} { diff --git a/rtpreceiver.go b/rtpreceiver.go index f7d83d6fae5..2457ba080a8 100644 --- a/rtpreceiver.go +++ b/rtpreceiver.go @@ -463,6 +463,9 @@ func (r *RTPReceiver) receiveForRtx(ssrc SSRC, rsid string, streamInfo *intercep continue } + if attributes == nil { + attributes = make(interceptor.Attributes) + } attributes.Set(AttributeRtxPayloadType, b[1]&0x7F) attributes.Set(AttributeRtxSequenceNumber, binary.BigEndian.Uint16(b[2:4])) attributes.Set(AttributeRtxSsrc, binary.BigEndian.Uint32(b[8:12])) diff --git a/rtptransceiver.go b/rtptransceiver.go index 15d28f720d1..4ba732e8a1e 100644 --- a/rtptransceiver.go +++ b/rtptransceiver.go @@ -266,12 +266,16 @@ func satisfyTypeAndDirection(remoteKind RTPCodecType, remoteDirection RTPTransce // handleUnknownRTPPacket consumes a single RTP Packet and returns information that is helpful // for demuxing and handling an unknown SSRC (usually for Simulcast) -func handleUnknownRTPPacket(buf []byte, midExtensionID, streamIDExtensionID, repairStreamIDExtensionID uint8, mid, rid, rsid *string) (payloadType PayloadType, err error) { +func handleUnknownRTPPacket(buf []byte, midExtensionID, streamIDExtensionID, repairStreamIDExtensionID uint8, mid, rid, rsid *string) (payloadType PayloadType, paddingOnly bool, err error) { rp := &rtp.Packet{} if err = rp.Unmarshal(buf); err != nil { return } + if rp.Padding && len(rp.Payload) == 0 { + paddingOnly = true + } + if !rp.Header.Extension { return }