Skip to content

Commit

Permalink
fix unmarshal rtcp keep doing allocation
Browse files Browse the repository at this point in the history
  • Loading branch information
Yohan Totting committed Sep 18, 2024
1 parent 294f613 commit 1b2cf63
Show file tree
Hide file tree
Showing 2 changed files with 86 additions and 1 deletion.
6 changes: 5 additions & 1 deletion client.go
Original file line number Diff line number Diff line change
Expand Up @@ -1044,7 +1044,7 @@ func readRTCP(r *webrtc.RTPSender, b []byte) ([]rtcp.Packet, interceptor.Attribu
return nil, nil, err
}

pkts, err := rtcp.Unmarshal(b[:i])
pkts, err := Unmarshal(b[:i])
if err != nil {
return nil, nil, err
}
Expand Down Expand Up @@ -1080,8 +1080,12 @@ func (c *Client) enableReportAndStats(rtpSender *webrtc.RTPSender, track iClient
switch p.(type) {
case *rtcp.PictureLossIndication:
track.RequestPLI()
pictureLossIndicationPool.Put(p)
case *rtcp.FullIntraRequest:
track.RequestPLI()
fullIntraRequestPool.Put(p)
default:
rawPacketPool.Put(p)
}
}
}
Expand Down
81 changes: 81 additions & 0 deletions rtcp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package sfu

import (
"errors"
"sync"

"github.com/pion/rtcp"
)

type Packet interface {
DestinationSSRC() []uint32
Marshal() ([]byte, error)
Unmarshal(rawPacket []byte) error
MarshalSize() int
Release()
}

var (
pictureLossIndicationPool = sync.Pool{New: func() interface{} { return new(rtcp.PictureLossIndication) }}
fullIntraRequestPool = sync.Pool{New: func() interface{} { return new(rtcp.FullIntraRequest) }}
rawPacketPool = sync.Pool{New: func() interface{} { return new(rtcp.RawPacket) }}

errPacketTooShort = errors.New("rtcp: packet too short")
errInvalidHeader = errors.New("rtcp: invalid header")
)

func unmarshal(rawData []byte) (packet rtcp.Packet, bytesprocessed int, err error) {
var h rtcp.Header

err = h.Unmarshal(rawData)
if err != nil {
return nil, 0, err
}

bytesprocessed = int(h.Length+1) * 4
if bytesprocessed > len(rawData) {
return nil, 0, errPacketTooShort
}
inPacket := rawData[:bytesprocessed]

switch h.Type {

case rtcp.TypePayloadSpecificFeedback:
switch h.Count {
case rtcp.FormatPLI:
packet = pictureLossIndicationPool.Get().(*rtcp.PictureLossIndication)
case rtcp.FormatFIR:
packet = fullIntraRequestPool.Get().(*rtcp.FullIntraRequest)
default:
packet = rawPacketPool.Get().(*rtcp.RawPacket)
}
default:
packet = rawPacketPool.Get().(*rtcp.RawPacket)
}

err = packet.Unmarshal(inPacket)

return packet, bytesprocessed, err
}

func Unmarshal(rawData []byte) ([]rtcp.Packet, error) {
var packets []rtcp.Packet
for len(rawData) != 0 {
p, processed, err := unmarshal(rawData)
if err != nil {
return nil, err
}

packets = append(packets, p)
rawData = rawData[processed:]
}

switch len(packets) {
// Empty packet
case 0:
return nil, errInvalidHeader
// Multiple Packets
default:
return packets, nil
}
}

0 comments on commit 1b2cf63

Please sign in to comment.