diff --git a/README.md b/README.md index 374d5f09..00eacf96 100644 --- a/README.md +++ b/README.md @@ -44,8 +44,8 @@ Features: * Utilities * Parse RTSP elements * Encode/decode format-specific frames into/from RTP packets. The following formats are supported: - * Video: H264, H265, M-JPEG, VP8, VP9, MPEG-4 Video (H263, Xvid) - * Audio: G711 (PCMA, PCMU), G722, LPCM, MPEG-2 Audio (MP3), MPEG-4 Audio (AAC), Opus + * Video: AV1, VP9, VP8, H265, H264, MPEG-4 Video (H263, Xvid), M-JPEG + * Audio: Opus, MPEG-4 Audio (AAC), MPEG-2 Audio (MP3), G722, G711 (PCMA, PCMU), LPCM ## Table of contents @@ -97,6 +97,7 @@ https://pkg.go.dev/github.com/bluenviron/gortsplib/v3#pkg-index ## Standards +* [Codec standards](https://github.com/bluenviron/mediacommon#standards) * [RFC2326, RTSP 1.0](https://datatracker.ietf.org/doc/html/rfc2326) * [RFC7826, RTSP 2.0](https://datatracker.ietf.org/doc/html/rfc7826) * [RFC8866, SDP: Session Description Protocol](https://datatracker.ietf.org/doc/html/rfc8866) @@ -113,9 +114,6 @@ https://pkg.go.dev/github.com/bluenviron/gortsplib/v3#pkg-index * [RFC7587, RTP Payload Format for the Opus Speech and Audio Codec](https://datatracker.ietf.org/doc/html/rfc7587) * [RFC3640, RTP Payload Format for Transport of MPEG-4 Elementary Streams](https://datatracker.ietf.org/doc/html/rfc3640) * [RTP Payload Format For AV1 (v1.0)](https://aomediacodec.github.io/av1-rtp-spec/) -* [ITU-T Rec. H.264 (08/2021)](https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-H.264-202108-I!!PDF-E&type=items) -* [ITU-T Rec. H.265 (08/2021)](https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-H.265-202108-I!!PDF-E&type=items) -* ISO 14496-3, Coding of audio-visual objects, part 3, Audio * [Golang project layout](https://github.com/golang-standards/project-layout) ## Links diff --git a/go.mod b/go.mod index 600d6bd8..fe5f23bc 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.18 require ( github.com/asticode/go-astits v1.11.0 - github.com/bluenviron/mediacommon v0.4.2 + github.com/bluenviron/mediacommon v0.5.0 github.com/google/uuid v1.3.0 github.com/pion/rtcp v1.2.10 github.com/pion/rtp v0.0.0-20230107162714-c3ea6851e25b diff --git a/go.sum b/go.sum index d38459f3..b133ce68 100644 --- a/go.sum +++ b/go.sum @@ -2,8 +2,8 @@ github.com/asticode/go-astikit v0.30.0 h1:DkBkRQRIxYcknlaU7W7ksNfn4gMFsB0tqMJflx github.com/asticode/go-astikit v0.30.0/go.mod h1:h4ly7idim1tNhaVkdVBeXQZEE3L0xblP7fCWbgwipF0= github.com/asticode/go-astits v1.11.0 h1:GTHUXht0ZXAJXsVbsLIcyfHr1Bchi4QQwMARw2ZWAng= github.com/asticode/go-astits v1.11.0/go.mod h1:QSHmknZ51pf6KJdHKZHJTLlMegIrhega3LPWz3ND/iI= -github.com/bluenviron/mediacommon v0.4.2 h1:rdghY3g70+fdviapO2hL6CHpOGeTd7KbH1aEZnMwh88= -github.com/bluenviron/mediacommon v0.4.2/go.mod h1:t0dqPsWUTchyvib0MhixIwXEgvDX4V9G+I0GzWLQRb8= +github.com/bluenviron/mediacommon v0.5.0 h1:YsVFlEknaXWhZGfz+Y1QbuzXLMVSmHODc7OnRqZoITY= +github.com/bluenviron/mediacommon v0.5.0/go.mod h1:t0dqPsWUTchyvib0MhixIwXEgvDX4V9G+I0GzWLQRb8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/pkg/formats/av1.go b/pkg/formats/av1.go index 4d21135c..ac11d5b0 100644 --- a/pkg/formats/av1.go +++ b/pkg/formats/av1.go @@ -1,10 +1,12 @@ -package formats +package formats //nolint:dupl import ( "fmt" "strconv" "github.com/pion/rtp" + + "github.com/bluenviron/gortsplib/v3/pkg/formats/rtpav1" ) // AV1 is a RTP format that uses the AV1 codec. @@ -94,3 +96,19 @@ func (f *AV1) FMTP() map[string]string { func (f *AV1) PTSEqualsDTS(*rtp.Packet) bool { return true } + +// CreateDecoder creates a decoder able to decode the content of the format. +func (f *AV1) CreateDecoder() *rtpav1.Decoder { + d := &rtpav1.Decoder{} + d.Init() + return d +} + +// CreateEncoder creates an encoder able to encode the content of the format. +func (f *AV1) CreateEncoder() *rtpav1.Encoder { + e := &rtpav1.Encoder{ + PayloadType: f.PayloadTyp, + } + e.Init() + return e +} diff --git a/pkg/formats/av1_test.go b/pkg/formats/av1_test.go index eaa2f1b1..1f638435 100644 --- a/pkg/formats/av1_test.go +++ b/pkg/formats/av1_test.go @@ -15,3 +15,17 @@ func TestAV1Attributes(t *testing.T) { require.Equal(t, 90000, format.ClockRate()) require.Equal(t, true, format.PTSEqualsDTS(&rtp.Packet{})) } + +func TestAV1DecEncoder(t *testing.T) { + format := &AV1{} + + enc := format.CreateEncoder() + pkts, err := enc.Encode([][]byte{{0x01, 0x02, 0x03, 0x04}}, 0) + require.NoError(t, err) + require.Equal(t, format.PayloadType(), pkts[0].PayloadType) + + dec := format.CreateDecoder() + byts, _, err := dec.Decode(pkts[0]) + require.NoError(t, err) + require.Equal(t, [][]byte{{0x01, 0x02, 0x03, 0x04}}, byts) +} diff --git a/pkg/formats/rtpav1/decoder.go b/pkg/formats/rtpav1/decoder.go new file mode 100644 index 00000000..41cd035c --- /dev/null +++ b/pkg/formats/rtpav1/decoder.go @@ -0,0 +1,150 @@ +package rtpav1 + +import ( + "errors" + "fmt" + "time" + + "github.com/bluenviron/mediacommon/pkg/codecs/av1" + "github.com/pion/rtp" + "github.com/pion/rtp/codecs" + + "github.com/bluenviron/gortsplib/v3/pkg/rtptime" +) + +// ErrMorePacketsNeeded is returned when more packets are needed. +var ErrMorePacketsNeeded = errors.New("need more packets") + +// ErrNonStartingPacketAndNoPrevious is returned when we received a non-starting +// packet of a fragmented NALU and we didn't received anything before. +// It's normal to receive this when decoding a stream that has been already +// running for some time. +var ErrNonStartingPacketAndNoPrevious = errors.New( + "received a non-starting fragment without any previous starting fragment") + +func joinFragments(fragments [][]byte, size int) []byte { + ret := make([]byte, size) + n := 0 + for _, p := range fragments { + n += copy(ret[n:], p) + } + return ret +} + +// Decoder is a RTP/AV1 decoder. +// Specification: https://aomediacodec.github.io/av1-rtp-spec/ +type Decoder struct { + timeDecoder *rtptime.Decoder + firstPacketReceived bool + fragmentsSize int + fragments [][]byte + + // for DecodeUntilMarker() + obuBuffer [][]byte +} + +// Init initializes the decoder. +func (d *Decoder) Init() { + d.timeDecoder = rtptime.NewDecoder(90000) +} + +// Decode decodes OBUs from a RTP packet. +func (d *Decoder) Decode(pkt *rtp.Packet) ([][]byte, time.Duration, error) { + var av1header codecs.AV1Packet + _, err := av1header.Unmarshal(pkt.Payload) + if err != nil { + d.fragments = d.fragments[:0] // discard pending fragments + d.fragmentsSize = 0 + return nil, 0, fmt.Errorf("invalid header: %v", err) + } + + for _, el := range av1header.OBUElements { + if len(el) == 0 { + return nil, 0, fmt.Errorf("invalid OBU fragment") + } + } + + if av1header.Z { + if len(d.fragments) == 0 { + if !d.firstPacketReceived { + return nil, 0, ErrNonStartingPacketAndNoPrevious + } + + return nil, 0, fmt.Errorf("received a subsequent fragment without previous fragments") + } + + d.fragmentsSize += len(av1header.OBUElements[0]) + if d.fragmentsSize > av1.MaxOBUSize { + d.fragments = d.fragments[:0] + d.fragmentsSize = 0 + return nil, 0, fmt.Errorf("OBU size (%d) is too big, maximum is %d", d.fragmentsSize, av1.MaxOBUSize) + } + + d.fragments = append(d.fragments, av1header.OBUElements[0]) + av1header.OBUElements = av1header.OBUElements[1:] + } + + d.firstPacketReceived = true + + var obus [][]byte + + if len(av1header.OBUElements) > 0 { + if d.fragmentsSize != 0 { + obus = append(obus, joinFragments(d.fragments, d.fragmentsSize)) + d.fragments = d.fragments[:0] + d.fragmentsSize = 0 + } + + if av1header.Y { + elementCount := len(av1header.OBUElements) + + d.fragmentsSize += len(av1header.OBUElements[elementCount-1]) + if d.fragmentsSize > av1.MaxOBUSize { + d.fragments = d.fragments[:0] + d.fragmentsSize = 0 + return nil, 0, fmt.Errorf("OBU size (%d) is too big, maximum is %d", d.fragmentsSize, av1.MaxOBUSize) + } + + d.fragments = append(d.fragments, av1header.OBUElements[elementCount-1]) + av1header.OBUElements = av1header.OBUElements[:elementCount-1] + } + + obus = append(obus, av1header.OBUElements...) + } else if !av1header.Y { + obus = append(obus, joinFragments(d.fragments, d.fragmentsSize)) + d.fragments = d.fragments[:0] + d.fragmentsSize = 0 + } + + if len(obus) == 0 { + return nil, 0, ErrMorePacketsNeeded + } + + return obus, d.timeDecoder.Decode(pkt.Timestamp), nil +} + +// DecodeUntilMarker decodes OBUs from a RTP packet and puts them in a buffer. +// When a packet has the marker flag (meaning that all OBUs with the same PTS have +// been received), the buffer is returned. +func (d *Decoder) DecodeUntilMarker(pkt *rtp.Packet) ([][]byte, time.Duration, error) { + obus, pts, err := d.Decode(pkt) + if err != nil { + return nil, 0, err + } + + if (len(d.obuBuffer) + len(obus)) > av1.MaxOBUsPerTemporalUnit { + return nil, 0, fmt.Errorf("OBU count (%d) exceeds maximum allowed (%d)", + len(d.obuBuffer)+len(obus), av1.MaxOBUsPerTemporalUnit) + } + + d.obuBuffer = append(d.obuBuffer, obus...) + + if !pkt.Marker { + return nil, 0, ErrMorePacketsNeeded + } + + ret := d.obuBuffer + d.obuBuffer = d.obuBuffer[:0] + + return ret, pts, nil +} diff --git a/pkg/formats/rtpav1/decoder_test.go b/pkg/formats/rtpav1/decoder_test.go new file mode 100644 index 00000000..939a72dd --- /dev/null +++ b/pkg/formats/rtpav1/decoder_test.go @@ -0,0 +1,62 @@ +package rtpav1 + +import ( + "testing" + + "github.com/pion/rtp" + "github.com/stretchr/testify/require" +) + +func TestDecode(t *testing.T) { + for _, ca := range cases { + t.Run(ca.name, func(t *testing.T) { + d := &Decoder{} + d.Init() + + var obus [][]byte + + for _, pkt := range ca.pkts { + addOBUs, _, err := d.Decode(pkt) + if err == ErrMorePacketsNeeded { + continue + } + + require.NoError(t, err) + obus = append(obus, addOBUs...) + } + + require.Equal(t, ca.obus, obus) + }) + } +} + +func FuzzDecoder(f *testing.F) { + f.Fuzz(func(t *testing.T, a []byte, am bool, b []byte, bm bool) { + d := &Decoder{} + d.Init() + + d.Decode(&rtp.Packet{ + Header: rtp.Header{ + Version: 2, + Marker: am, + PayloadType: 96, + SequenceNumber: 17645, + Timestamp: 2289527317, + SSRC: 0x9dbb7812, + }, + Payload: a, + }) + + d.Decode(&rtp.Packet{ + Header: rtp.Header{ + Version: 2, + Marker: bm, + PayloadType: 96, + SequenceNumber: 17646, + Timestamp: 2289527317, + SSRC: 0x9dbb7812, + }, + Payload: b, + }) + }) +} diff --git a/pkg/formats/rtpav1/encoder.go b/pkg/formats/rtpav1/encoder.go new file mode 100644 index 00000000..8f9e04a4 --- /dev/null +++ b/pkg/formats/rtpav1/encoder.go @@ -0,0 +1,147 @@ +package rtpav1 + +import ( + "crypto/rand" + "time" + + "github.com/bluenviron/mediacommon/pkg/codecs/av1" + "github.com/pion/rtp" + + "github.com/bluenviron/gortsplib/v3/pkg/rtptime" +) + +const ( + rtpVersion = 2 +) + +func randUint32() uint32 { + var b [4]byte + rand.Read(b[:]) + return uint32(b[0])<<24 | uint32(b[1])<<16 | uint32(b[2])<<8 | uint32(b[3]) +} + +// Encoder is a RTP/AV1 encoder. +// Specification: https://aomediacodec.github.io/av1-rtp-spec/ +type Encoder struct { + // payload type of packets. + PayloadType uint8 + + // SSRC of packets (optional). + // It defaults to a random value. + SSRC *uint32 + + // initial sequence number of packets (optional). + // It defaults to a random value. + InitialSequenceNumber *uint16 + + // initial timestamp of packets (optional). + // It defaults to a random value. + InitialTimestamp *uint32 + + // maximum size of packet payloads (optional). + // It defaults to 1460. + PayloadMaxSize int + + sequenceNumber uint16 + timeEncoder *rtptime.Encoder +} + +// Init initializes the encoder. +func (e *Encoder) Init() { + if e.SSRC == nil { + v := randUint32() + e.SSRC = &v + } + if e.InitialSequenceNumber == nil { + v := uint16(randUint32()) + e.InitialSequenceNumber = &v + } + if e.InitialTimestamp == nil { + v := randUint32() + e.InitialTimestamp = &v + } + if e.PayloadMaxSize == 0 { + e.PayloadMaxSize = 1460 // 1500 (UDP MTU) - 20 (IP header) - 8 (UDP header) - 12 (RTP header) + } + + e.sequenceNumber = *e.InitialSequenceNumber + e.timeEncoder = rtptime.NewEncoder(90000, *e.InitialTimestamp) +} + +// Encode encodes OBUs into RTP packets. +func (e *Encoder) Encode(obus [][]byte, pts time.Duration) ([]*rtp.Packet, error) { + isKeyFrame, err := av1.ContainsKeyFrame(obus) + if err != nil { + return nil, err + } + + ts := e.timeEncoder.Encode(pts) + var curPacket *rtp.Packet + var packets []*rtp.Packet + curPayloadLen := 0 + + createNewPacket := func(z bool) { + curPacket = &rtp.Packet{ + Header: rtp.Header{ + Version: rtpVersion, + PayloadType: e.PayloadType, + SequenceNumber: e.sequenceNumber, + Timestamp: ts, + SSRC: *e.SSRC, + }, + Payload: []byte{0}, + } + e.sequenceNumber++ + packets = append(packets, curPacket) + curPayloadLen = 1 + + if z { + curPacket.Payload[0] |= 1 << 7 + } + } + + finalizeCurPacket := func(y bool) { + if y { + curPacket.Payload[0] |= 1 << 6 + } + } + + createNewPacket(false) + + for _, obu := range obus { + for { + avail := e.PayloadMaxSize - curPayloadLen + obuLen := len(obu) + needed := obuLen + 2 + + if needed <= avail { + le := av1.LEB128Marshal(uint(obuLen)) + curPacket.Payload = append(curPacket.Payload, le...) + curPacket.Payload = append(curPacket.Payload, obu...) + curPayloadLen += len(le) + obuLen + break + } + + if avail > 2 { + fragmentLen := avail - 2 + le := av1.LEB128Marshal(uint(fragmentLen)) + curPacket.Payload = append(curPacket.Payload, le...) + curPacket.Payload = append(curPacket.Payload, obu[:fragmentLen]...) + obu = obu[fragmentLen:] + } + + finalizeCurPacket(true) + createNewPacket(true) + } + } + + finalizeCurPacket(false) + + if isKeyFrame { + packets[0].Payload[0] |= 1 << 3 + } + + packets[len(packets)-1].Marker = true + + return packets, nil +} diff --git a/pkg/formats/rtpav1/encoder_test.go b/pkg/formats/rtpav1/encoder_test.go new file mode 100644 index 00000000..54f1cc42 --- /dev/null +++ b/pkg/formats/rtpav1/encoder_test.go @@ -0,0 +1,1011 @@ +package rtpav1 + +import ( + "testing" + + "github.com/pion/rtp" + "github.com/stretchr/testify/require" +) + +var shortOBU = []byte{ + 0x0a, 0x0e, 0x00, 0x00, 0x00, 0x4a, 0xab, 0xbf, + 0xc3, 0x77, 0x6b, 0xe4, 0x40, 0x40, 0x40, 0x41, +} + +var longOBU = []byte{ + 0x30, 0x30, 0xca, 0x08, 0x12, 0xfd, 0xfd, 0x78, + 0x89, 0xe5, 0x3e, 0xa3, 0x80, 0x08, 0x20, 0x82, + 0x08, 0x54, 0x50, 0x00, 0x30, 0x00, 0x00, 0x66, + 0x00, 0xeb, 0xcd, 0xc5, 0x72, 0x25, 0x5a, 0x0a, + 0xc3, 0x4a, 0x43, 0x15, 0x59, 0x13, 0x5f, 0xb9, + 0x39, 0x19, 0xf1, 0xca, 0x26, 0xc7, 0x59, 0xa7, + 0x66, 0xe4, 0xa5, 0xff, 0x3a, 0xba, 0x3f, 0x62, + 0xfc, 0x58, 0x07, 0xd0, 0x18, 0xd6, 0xb2, 0x90, + 0x72, 0xf4, 0x57, 0xbd, 0x5d, 0x72, 0x92, 0x8c, + 0x71, 0x48, 0x17, 0x89, 0x65, 0xa9, 0x9e, 0xa2, + 0x81, 0x9a, 0x83, 0x66, 0x11, 0xd7, 0xe7, 0x41, + 0x35, 0xb7, 0x8a, 0xb3, 0xd0, 0x90, 0x54, 0x2a, + 0x48, 0xea, 0x65, 0xd1, 0xb0, 0x83, 0xda, 0xbb, + 0x61, 0xff, 0xc4, 0xd0, 0x06, 0x78, 0x35, 0xc2, + 0xf7, 0x15, 0x16, 0xe5, 0xc3, 0xf0, 0x9f, 0x7f, + 0x1a, 0xd6, 0xad, 0xd4, 0x41, 0xa4, 0xf4, 0x40, + 0x41, 0x00, 0x78, 0x5c, 0x14, 0x08, 0x57, 0x3d, + 0x96, 0xc2, 0x0b, 0xb5, 0x03, 0xce, 0x7d, 0xe6, + 0x50, 0xd1, 0xbc, 0x3e, 0x1e, 0x84, 0x62, 0x1a, + 0xd1, 0xfe, 0x52, 0x9e, 0x79, 0x26, 0x51, 0xc8, + 0x14, 0x54, 0xf2, 0x77, 0xe6, 0x25, 0x0f, 0x5f, + 0xec, 0x66, 0x33, 0xdb, 0xd0, 0x9f, 0x5a, 0xf9, + 0xbc, 0xc4, 0x9b, 0x31, 0x8c, 0x6f, 0xe6, 0x2a, + 0x50, 0x65, 0x1d, 0x45, 0xaf, 0x19, 0xd4, 0xde, + 0xf8, 0x33, 0x43, 0x48, 0x57, 0x00, 0x80, 0x5b, + 0xaa, 0x3e, 0x1b, 0xf7, 0x21, 0xc1, 0x56, 0x5e, + 0xfb, 0xdb, 0x43, 0xa8, 0x7b, 0xde, 0x82, 0xc1, + 0x45, 0x5a, 0x36, 0x04, 0x20, 0xa8, 0xa3, 0x0b, + 0xa9, 0xa8, 0x6d, 0xe1, 0xfd, 0x13, 0x0d, 0x38, + 0xef, 0x00, 0xd5, 0x00, 0xe5, 0x2d, 0x69, 0x67, + 0x17, 0x59, 0xd9, 0xda, 0x61, 0x95, 0xac, 0x55, + 0x3a, 0xc5, 0x77, 0x1e, 0xbe, 0xa5, 0x58, 0x7a, + 0xbb, 0x09, 0xbd, 0x46, 0xab, 0x82, 0x60, 0x13, + 0x8f, 0x8b, 0xfb, 0x29, 0xe0, 0x7f, 0xa5, 0xca, + 0x25, 0xfa, 0x77, 0x07, 0x88, 0x51, 0xdb, 0xc2, + 0x99, 0x5f, 0xad, 0xe1, 0x45, 0x28, 0x0e, 0x00, + 0x86, 0x79, 0x60, 0xe2, 0x36, 0x9a, 0x41, 0x21, + 0x01, 0xdf, 0x3d, 0x0c, 0x31, 0x37, 0xa4, 0x0b, + 0x00, 0xe6, 0x43, 0xfb, 0x28, 0x05, 0x2c, 0xff, + 0x40, 0x1c, 0x23, 0x6d, 0x4f, 0x58, 0x00, 0xe1, + 0xc4, 0xb2, 0x05, 0x3a, 0x03, 0xa4, 0xde, 0xf4, + 0x13, 0x5e, 0x8c, 0x45, 0xc2, 0x3b, 0xf0, 0x2c, + 0x00, 0x28, 0x0b, 0xe2, 0x7d, 0xa4, 0x27, 0x78, + 0xf0, 0xfa, 0x3f, 0x0a, 0xa9, 0xac, 0x20, 0xa0, + 0xe2, 0x33, 0xe8, 0xc6, 0xa7, 0x69, 0x6f, 0x4c, + 0xec, 0x67, 0x06, 0x79, 0x27, 0x1d, 0x69, 0xe3, + 0xa6, 0xad, 0x6e, 0x63, 0x97, 0xd2, 0xe3, 0xaa, + 0xd4, 0xc5, 0x6d, 0xaa, 0x29, 0xfa, 0xc3, 0x4b, + 0x23, 0xec, 0xe7, 0x5f, 0xdd, 0xf8, 0x45, 0x55, + 0x62, 0xec, 0x3c, 0xe8, 0x73, 0xf0, 0x63, 0x04, + 0x6f, 0x88, 0xa7, 0x4d, 0x7c, 0x28, 0xef, 0x20, + 0x0d, 0x00, 0xf9, 0xba, 0xe5, 0x09, 0x5d, 0xc2, + 0x8d, 0x7d, 0x18, 0x2c, 0x2f, 0xff, 0x93, 0x88, + 0x2d, 0x00, 0xf9, 0xaf, 0x22, 0x68, 0x70, 0x72, + 0xe4, 0x36, 0x22, 0x15, 0x5f, 0x7a, 0xef, 0xd9, + 0x03, 0x25, 0xf5, 0x17, 0x68, 0x30, 0xee, 0x2b, + 0xed, 0xe8, 0x0c, 0x1a, 0x32, 0x72, 0x62, 0xd4, + 0x74, 0x69, 0xf1, 0x9a, 0xcf, 0x9b, 0x52, 0xfc, + 0x56, 0xe3, 0xda, 0x73, 0x09, 0x33, 0x95, 0x08, + 0x77, 0x00, 0x09, 0x17, 0x4d, 0xb7, 0xc4, 0x32, + 0xcd, 0xf9, 0x33, 0x7f, 0x78, 0x44, 0x33, 0xf3, + 0x94, 0x5d, 0x74, 0x14, 0x53, 0x3e, 0xc1, 0xa6, + 0x62, 0x3a, 0x94, 0x41, 0xc9, 0x4d, 0x05, 0x87, + 0x7d, 0x92, 0xd9, 0x12, 0xb4, 0x9a, 0x1f, 0x43, + 0xf4, 0x54, 0x0c, 0xb4, 0x6c, 0xd0, 0x16, 0xd7, + 0x46, 0xe2, 0x5e, 0xdc, 0x56, 0xff, 0x42, 0x72, + 0xe4, 0x97, 0x8f, 0xdb, 0x2f, 0x27, 0xbd, 0x4c, + 0xa3, 0x4e, 0x43, 0x4a, 0x0b, 0x46, 0x45, 0x36, + 0x80, 0x0d, 0xd4, 0x87, 0xc7, 0x1a, 0xf8, 0x5f, + 0x9c, 0xf4, 0x10, 0x82, 0xa8, 0x28, 0xa7, 0xd1, + 0xbf, 0xc1, 0x61, 0x5a, 0x73, 0xbd, 0xe9, 0x44, + 0x66, 0x5a, 0x2b, 0x14, 0x4c, 0xa5, 0x5d, 0x3d, + 0x38, 0xfb, 0xd4, 0xa8, 0x24, 0xbe, 0xe4, 0x99, + 0xa1, 0x98, 0x90, 0x72, 0x67, 0x1f, 0x3b, 0x96, + 0xae, 0x60, 0x7a, 0x00, 0xf2, 0x11, 0x13, 0x9f, + 0xc4, 0xb5, 0x63, 0xd7, 0x63, 0xb6, 0x64, 0xe3, + 0xbb, 0xf1, 0x96, 0x9e, 0x77, 0xab, 0xc4, 0xa8, + 0x39, 0xd5, 0x22, 0xe9, 0xee, 0xad, 0x1f, 0x91, + 0xff, 0x56, 0x3e, 0x68, 0x89, 0x63, 0x11, 0xc8, + 0x98, 0xa1, 0x7e, 0xd9, 0x37, 0xb2, 0x94, 0x23, + 0xfb, 0x67, 0xb7, 0xa0, 0xaa, 0x0f, 0xe7, 0xb6, + 0xe1, 0xb8, 0xc3, 0x73, 0xe3, 0xae, 0x07, 0xe6, + 0xf7, 0xc8, 0x35, 0x03, 0xc5, 0x7a, 0xfc, 0x48, + 0xd4, 0xe2, 0x61, 0x7a, 0x22, 0xdd, 0x78, 0x4b, + 0xef, 0xa4, 0xde, 0x27, 0x62, 0xdd, 0xa1, 0x76, + 0xe5, 0xeb, 0x83, 0xa3, 0x18, 0xde, 0xe9, 0x99, + 0x37, 0x66, 0x34, 0x20, 0xaf, 0x67, 0x2b, 0xdd, + 0xa4, 0x69, 0xeb, 0x7d, 0x71, 0x0f, 0x24, 0xef, + 0x88, 0x49, 0x8c, 0xe5, 0x33, 0xfa, 0xf3, 0x3e, + 0xff, 0x46, 0x10, 0x5d, 0x25, 0x97, 0x7f, 0x8e, + 0x00, 0xe2, 0x08, 0x0e, 0x39, 0x65, 0x4c, 0xa5, + 0x1b, 0x5f, 0x5a, 0xa8, 0xab, 0xb1, 0x4a, 0x55, + 0xf0, 0x41, 0x9e, 0xf5, 0xcd, 0x2c, 0x34, 0x56, + 0x11, 0xda, 0x96, 0x68, 0xe4, 0x39, 0x8d, 0xfe, + 0x40, 0xb0, 0x0b, 0x05, 0x5d, 0xf4, 0xba, 0x27, + 0x1a, 0x3b, 0xed, 0xee, 0x88, 0x07, 0x59, 0x40, + 0xf6, 0x6f, 0x44, 0x1a, 0x5f, 0x3d, 0x42, 0xb2, + 0xa7, 0x5d, 0x07, 0xd5, 0x7e, 0x95, 0x36, 0xc9, + 0xa3, 0xd3, 0x45, 0x56, 0x70, 0x92, 0x79, 0xc9, + 0xd7, 0xfd, 0x88, 0xa4, 0x89, 0x9a, 0x94, 0xbd, + 0x9d, 0x49, 0xec, 0x32, 0xc4, 0xee, 0x87, 0xd7, + 0x0a, 0xf8, 0xab, 0x23, 0x70, 0x3b, 0xbd, 0xd6, + 0x34, 0x86, 0x3a, 0x05, 0x68, 0x95, 0x31, 0x81, + 0x2d, 0x6d, 0xde, 0x54, 0xfe, 0x0b, 0xa9, 0x72, + 0x3c, 0x78, 0xb7, 0xf5, 0x84, 0x67, 0x39, 0x4f, + 0x2d, 0xbb, 0xcb, 0x22, 0x2d, 0xed, 0xf2, 0xc1, + 0x56, 0xf8, 0x11, 0xf9, 0xee, 0x81, 0xd8, 0x64, + 0x07, 0xbf, 0xb4, 0x69, 0xdb, 0xda, 0x0c, 0xf5, + 0x20, 0x00, 0xf8, 0x26, 0x7b, 0x31, 0x54, 0x09, + 0x24, 0xbf, 0x7c, 0xf5, 0xad, 0x76, 0xbb, 0xcc, + 0x89, 0xee, 0x5b, 0x2a, 0x23, 0x12, 0x1c, 0x69, + 0x50, 0xdd, 0x03, 0x0d, 0xe4, 0xca, 0xb8, 0x59, + 0x7c, 0x91, 0xa0, 0x82, 0x00, 0x01, 0x9e, 0x1e, + 0x4d, 0x87, 0xf7, 0xab, 0x3d, 0x06, 0x6c, 0x95, + 0x90, 0x63, 0x57, 0x0f, 0x44, 0x4c, 0x49, 0x21, + 0x2e, 0x85, 0x47, 0x61, 0x02, 0x67, 0x57, 0xdc, + 0xde, 0x67, 0x92, 0x11, 0x34, 0x85, 0x05, 0x9e, + 0x25, 0xe4, 0x1b, 0x8e, 0xaa, 0xca, 0xd9, 0x4c, + 0x2c, 0x84, 0x30, 0xf1, 0xdc, 0x4a, 0x9b, 0x02, + 0xdd, 0x69, 0x5e, 0xcd, 0x31, 0x08, 0x27, 0xd1, + 0x83, 0xcd, 0x03, 0x4d, 0xd9, 0xf0, 0x0a, 0x69, + 0x8e, 0x8b, 0x88, 0x14, 0x98, 0x37, 0x8c, 0xad, + 0x93, 0x70, 0x04, 0xf8, 0x88, 0xa7, 0x67, 0xf0, + 0xfe, 0xa9, 0x49, 0x46, 0xbe, 0xab, 0x14, 0x8c, + 0x56, 0xea, 0x17, 0x52, 0x1f, 0x35, 0xfa, 0xd2, + 0xd4, 0xa4, 0xf6, 0xb6, 0x72, 0x25, 0x03, 0xbf, + 0xc1, 0x85, 0xe1, 0x3e, 0x3a, 0x19, 0xcb, 0xe3, + 0x7e, 0x15, 0x65, 0xd1, 0x33, 0x40, 0x2a, 0xd8, + 0x3f, 0x2c, 0x86, 0x12, 0x65, 0xe2, 0x60, 0x80, + 0x1b, 0x01, 0x0b, 0xd2, 0xcd, 0x3b, 0x24, 0x56, + 0x73, 0xcd, 0xa9, 0x34, 0xd1, 0x36, 0xd3, 0x26, + 0x6f, 0x49, 0x58, 0xcf, 0xb7, 0x39, 0x92, 0xa8, + 0x15, 0x47, 0x0f, 0x92, 0x68, 0x49, 0xa2, 0x91, + 0xe0, 0x55, 0xc8, 0xd9, 0xf1, 0x84, 0xc4, 0x41, + 0x67, 0xd9, 0x24, 0xf3, 0x0f, 0xdc, 0x3d, 0x6d, + 0x79, 0x4d, 0x0f, 0x35, 0x8b, 0xdf, 0x6d, 0xcd, + 0x66, 0x7e, 0x82, 0x09, 0xa3, 0x72, 0x1d, 0x3d, + 0x4b, 0x0f, 0xad, 0x7c, 0xbe, 0xdd, 0x96, 0x17, + 0x62, 0x26, 0x72, 0xe6, 0x1d, 0xb9, 0xf6, 0x9a, + 0x71, 0x52, 0x5a, 0x76, 0xbb, 0x4e, 0x11, 0x78, + 0xbe, 0x05, 0xe5, 0xf6, 0xaf, 0xf2, 0x66, 0xd3, + 0xe5, 0xdb, 0xfc, 0xd8, 0x96, 0x64, 0x8b, 0x7a, + 0xec, 0x9f, 0x3e, 0x0d, 0x7c, 0xd5, 0x20, 0xdf, + 0x50, 0x52, 0x57, 0x93, 0xa0, 0x03, 0x5a, 0xed, + 0x5c, 0xb4, 0xfa, 0x15, 0xf0, 0xda, 0xc4, 0x94, + 0xbf, 0xcb, 0x25, 0xc7, 0xda, 0x59, 0x5d, 0xb8, + 0x00, 0x00, 0x00, 0x56, 0x76, 0xe4, 0x62, 0x1c, + 0x71, 0x70, 0xf6, 0x7f, 0x20, 0x83, 0xee, 0x17, + 0x23, 0x56, 0x8c, 0x20, 0x9c, 0x65, 0x25, 0xe9, + 0x38, 0xe2, 0xd2, 0x66, 0xae, 0xa1, 0x47, 0x16, + 0xba, 0x5e, 0x87, 0xd4, 0x8b, 0x7e, 0x80, 0x9f, + 0x83, 0x4b, 0x27, 0x46, 0x97, 0x72, 0x2b, 0x88, + 0xd1, 0xf0, 0x92, 0xd4, 0x2a, 0x7e, 0x48, 0x63, + 0x95, 0x33, 0x13, 0x07, 0xf8, 0x79, 0x3a, 0x6b, + 0x67, 0x1c, 0x6f, 0x38, 0x80, 0x3c, 0xc6, 0xfa, + 0xb8, 0x4e, 0xd2, 0x01, 0xaf, 0x79, 0x37, 0x60, + 0xd6, 0x4d, 0x55, 0xcd, 0x1d, 0xf5, 0x15, 0x0f, + 0xb7, 0x8c, 0xa5, 0xec, 0x25, 0xe4, 0x45, 0xec, + 0xe6, 0xf9, 0xc2, 0x35, 0xea, 0xc6, 0x30, 0xa2, + 0x1f, 0x21, 0x13, 0x1f, 0x97, 0x95, 0xee, 0x69, + 0x63, 0xcf, 0x4b, 0xb2, 0xc3, 0xc0, 0x23, 0xc9, + 0x75, 0x2b, 0xd6, 0xac, 0x3c, 0xcb, 0x38, 0x73, + 0xa0, 0x5a, 0xa5, 0x7d, 0x3d, 0x23, 0xb1, 0x4c, + 0xc9, 0x1b, 0x12, 0xc4, 0x83, 0xe1, 0x62, 0x61, + 0xf3, 0x8c, 0x6a, 0x45, 0x95, 0xee, 0x74, 0x00, + 0x2f, 0x84, 0x77, 0xff, 0x16, 0x22, 0x02, 0xfe, + 0x4b, 0xd2, 0x57, 0x65, 0xee, 0x49, 0xcd, 0x7b, + 0xb5, 0xdb, 0x8e, 0x5a, 0xcb, 0x70, 0x7f, 0x78, + 0xbc, 0x35, 0x34, 0x3e, 0xcd, 0xf6, 0x24, 0x78, + 0x8f, 0xe8, 0x9e, 0x5c, 0x9c, 0x22, 0x4a, 0xf0, + 0xbc, 0x89, 0x64, 0x93, 0xcf, 0x20, 0xc8, 0xfd, + 0x27, 0xe2, 0x36, 0x86, 0x00, 0x61, 0xe8, 0xe2, + 0x9c, 0xad, 0x55, 0x98, 0x77, 0x2f, 0xfa, 0x28, + 0xb4, 0xa7, 0xda, 0xa4, 0x14, 0x06, 0x8c, 0x7a, + 0xd5, 0xdf, 0x0d, 0x32, 0x56, 0xcc, 0xd3, 0x70, + 0x71, 0x70, 0xd5, 0xb6, 0x41, 0x0f, 0x45, 0xb2, + 0xf0, 0x24, 0xa5, 0x23, 0x13, 0x70, 0x36, 0x07, + 0xcd, 0xc6, 0x75, 0xd8, 0x62, 0x8c, 0x7f, 0xa7, + 0xb9, 0x76, 0x16, 0xb3, 0x9a, 0x7e, 0x20, 0x27, + 0x27, 0x2d, 0x33, 0x60, 0x70, 0xa5, 0xef, 0x5c, + 0x9c, 0x6e, 0x5f, 0x2f, 0x20, 0x78, 0x58, 0x59, + 0x92, 0x15, 0xfe, 0x13, 0x07, 0x87, 0xc7, 0x3e, + 0x21, 0x04, 0x24, 0x33, 0x60, 0x15, 0x91, 0xfb, + 0xfe, 0xe8, 0xf8, 0xb9, 0xa6, 0x9a, 0xbf, 0x65, + 0xf3, 0x37, 0x40, 0xb8, 0x52, 0x69, 0x3f, 0x65, + 0x27, 0x36, 0x01, 0x92, 0xe8, 0xef, 0x51, 0x3e, + 0xcd, 0xf5, 0xcc, 0x4f, 0x8b, 0x4f, 0x7b, 0x38, + 0x3e, 0x43, 0x4d, 0xc0, 0xa4, 0xc6, 0x84, 0x79, + 0x8e, 0xf4, 0x4a, 0xe1, 0xa9, 0x2b, 0xd5, 0x34, + 0x00, 0x30, 0x94, 0x6a, 0x91, 0xa2, 0xd5, 0xc0, + 0xbf, 0xb5, 0x66, 0x59, 0x38, 0xc2, 0xa4, 0x75, + 0x96, 0x5b, 0x7a, 0xac, 0x9c, 0x05, 0x67, 0x99, + 0x2e, 0xba, 0x21, 0x1e, 0xac, 0x50, 0x01, 0x68, + 0x71, 0xac, 0x68, 0x6d, 0xc1, 0xf2, 0x2c, 0x51, + 0x1e, 0xb6, 0x64, 0x97, 0x3d, 0x9b, 0x2b, 0x89, + 0x66, 0xbd, 0x50, 0x4f, 0x5c, 0xec, 0x7c, 0xc8, + 0x51, 0x61, 0x74, 0xbd, 0x86, 0xb4, 0x6e, 0x71, + 0x59, 0x24, 0x59, 0xaf, 0x66, 0x54, 0x82, 0xdb, + 0xe2, 0x11, 0x6f, 0x87, 0x92, 0xf3, 0x63, 0xd4, + 0x4b, 0xd6, 0x26, 0x42, 0xf1, 0x2a, 0x66, 0x63, + 0x79, 0x5e, 0x7e, 0xfb, 0x3f, 0x85, 0xa7, 0x24, + 0xac, 0x53, 0xe2, 0x57, 0x56, 0xdd, 0xef, 0x7a, + 0xdf, 0xb6, 0x27, 0xaf, 0x25, 0x6a, 0x89, 0x4a, + 0x4c, 0xc3, 0xe6, 0x2e, 0xbe, 0x2b, 0x38, 0x07, + 0xe0, 0x96, 0x98, 0xaf, 0x85, 0xf4, 0x86, 0x7d, + 0xf4, 0xee, 0xe5, 0x78, +} + +var cases = []struct { + name string + obus [][]byte + pkts []*rtp.Packet +}{ + { + "single", + [][]byte{shortOBU}, + []*rtp.Packet{ + { + Header: rtp.Header{ + Version: 2, + Marker: true, + PayloadType: 96, + SequenceNumber: 17645, + Timestamp: 2289526357, + SSRC: 0x9dbb7812, + }, + Payload: []byte{ + 0x08, 0x10, + 0x0a, 0x0e, 0x00, 0x00, 0x00, 0x4a, 0xab, 0xbf, + 0xc3, 0x77, 0x6b, 0xe4, 0x40, 0x40, 0x40, 0x41, + }, + }, + }, + }, + { + "fragmented", + [][]byte{longOBU}, + []*rtp.Packet{ + { // nolint:dupl + Header: rtp.Header{ + Version: 2, + Marker: false, + PayloadType: 96, + SequenceNumber: 17645, + Timestamp: 2289526357, + SSRC: 0x9dbb7812, + }, + Payload: []byte{ + 0x40, 0xb1, 0x0b, 0x30, 0x30, 0xca, 0x08, 0x12, + 0xfd, 0xfd, 0x78, 0x89, 0xe5, 0x3e, 0xa3, 0x80, + 0x08, 0x20, 0x82, 0x08, 0x54, 0x50, 0x00, 0x30, + 0x00, 0x00, 0x66, 0x00, 0xeb, 0xcd, 0xc5, 0x72, + 0x25, 0x5a, 0x0a, 0xc3, 0x4a, 0x43, 0x15, 0x59, + 0x13, 0x5f, 0xb9, 0x39, 0x19, 0xf1, 0xca, 0x26, + 0xc7, 0x59, 0xa7, 0x66, 0xe4, 0xa5, 0xff, 0x3a, + 0xba, 0x3f, 0x62, 0xfc, 0x58, 0x07, 0xd0, 0x18, + 0xd6, 0xb2, 0x90, 0x72, 0xf4, 0x57, 0xbd, 0x5d, + 0x72, 0x92, 0x8c, 0x71, 0x48, 0x17, 0x89, 0x65, + 0xa9, 0x9e, 0xa2, 0x81, 0x9a, 0x83, 0x66, 0x11, + 0xd7, 0xe7, 0x41, 0x35, 0xb7, 0x8a, 0xb3, 0xd0, + 0x90, 0x54, 0x2a, 0x48, 0xea, 0x65, 0xd1, 0xb0, + 0x83, 0xda, 0xbb, 0x61, 0xff, 0xc4, 0xd0, 0x06, + 0x78, 0x35, 0xc2, 0xf7, 0x15, 0x16, 0xe5, 0xc3, + 0xf0, 0x9f, 0x7f, 0x1a, 0xd6, 0xad, 0xd4, 0x41, + 0xa4, 0xf4, 0x40, 0x41, 0x00, 0x78, 0x5c, 0x14, + 0x08, 0x57, 0x3d, 0x96, 0xc2, 0x0b, 0xb5, 0x03, + 0xce, 0x7d, 0xe6, 0x50, 0xd1, 0xbc, 0x3e, 0x1e, + 0x84, 0x62, 0x1a, 0xd1, 0xfe, 0x52, 0x9e, 0x79, + 0x26, 0x51, 0xc8, 0x14, 0x54, 0xf2, 0x77, 0xe6, + 0x25, 0x0f, 0x5f, 0xec, 0x66, 0x33, 0xdb, 0xd0, + 0x9f, 0x5a, 0xf9, 0xbc, 0xc4, 0x9b, 0x31, 0x8c, + 0x6f, 0xe6, 0x2a, 0x50, 0x65, 0x1d, 0x45, 0xaf, + 0x19, 0xd4, 0xde, 0xf8, 0x33, 0x43, 0x48, 0x57, + 0x00, 0x80, 0x5b, 0xaa, 0x3e, 0x1b, 0xf7, 0x21, + 0xc1, 0x56, 0x5e, 0xfb, 0xdb, 0x43, 0xa8, 0x7b, + 0xde, 0x82, 0xc1, 0x45, 0x5a, 0x36, 0x04, 0x20, + 0xa8, 0xa3, 0x0b, 0xa9, 0xa8, 0x6d, 0xe1, 0xfd, + 0x13, 0x0d, 0x38, 0xef, 0x00, 0xd5, 0x00, 0xe5, + 0x2d, 0x69, 0x67, 0x17, 0x59, 0xd9, 0xda, 0x61, + 0x95, 0xac, 0x55, 0x3a, 0xc5, 0x77, 0x1e, 0xbe, + 0xa5, 0x58, 0x7a, 0xbb, 0x09, 0xbd, 0x46, 0xab, + 0x82, 0x60, 0x13, 0x8f, 0x8b, 0xfb, 0x29, 0xe0, + 0x7f, 0xa5, 0xca, 0x25, 0xfa, 0x77, 0x07, 0x88, + 0x51, 0xdb, 0xc2, 0x99, 0x5f, 0xad, 0xe1, 0x45, + 0x28, 0x0e, 0x00, 0x86, 0x79, 0x60, 0xe2, 0x36, + 0x9a, 0x41, 0x21, 0x01, 0xdf, 0x3d, 0x0c, 0x31, + 0x37, 0xa4, 0x0b, 0x00, 0xe6, 0x43, 0xfb, 0x28, + 0x05, 0x2c, 0xff, 0x40, 0x1c, 0x23, 0x6d, 0x4f, + 0x58, 0x00, 0xe1, 0xc4, 0xb2, 0x05, 0x3a, 0x03, + 0xa4, 0xde, 0xf4, 0x13, 0x5e, 0x8c, 0x45, 0xc2, + 0x3b, 0xf0, 0x2c, 0x00, 0x28, 0x0b, 0xe2, 0x7d, + 0xa4, 0x27, 0x78, 0xf0, 0xfa, 0x3f, 0x0a, 0xa9, + 0xac, 0x20, 0xa0, 0xe2, 0x33, 0xe8, 0xc6, 0xa7, + 0x69, 0x6f, 0x4c, 0xec, 0x67, 0x06, 0x79, 0x27, + 0x1d, 0x69, 0xe3, 0xa6, 0xad, 0x6e, 0x63, 0x97, + 0xd2, 0xe3, 0xaa, 0xd4, 0xc5, 0x6d, 0xaa, 0x29, + 0xfa, 0xc3, 0x4b, 0x23, 0xec, 0xe7, 0x5f, 0xdd, + 0xf8, 0x45, 0x55, 0x62, 0xec, 0x3c, 0xe8, 0x73, + 0xf0, 0x63, 0x04, 0x6f, 0x88, 0xa7, 0x4d, 0x7c, + 0x28, 0xef, 0x20, 0x0d, 0x00, 0xf9, 0xba, 0xe5, + 0x09, 0x5d, 0xc2, 0x8d, 0x7d, 0x18, 0x2c, 0x2f, + 0xff, 0x93, 0x88, 0x2d, 0x00, 0xf9, 0xaf, 0x22, + 0x68, 0x70, 0x72, 0xe4, 0x36, 0x22, 0x15, 0x5f, + 0x7a, 0xef, 0xd9, 0x03, 0x25, 0xf5, 0x17, 0x68, + 0x30, 0xee, 0x2b, 0xed, 0xe8, 0x0c, 0x1a, 0x32, + 0x72, 0x62, 0xd4, 0x74, 0x69, 0xf1, 0x9a, 0xcf, + 0x9b, 0x52, 0xfc, 0x56, 0xe3, 0xda, 0x73, 0x09, + 0x33, 0x95, 0x08, 0x77, 0x00, 0x09, 0x17, 0x4d, + 0xb7, 0xc4, 0x32, 0xcd, 0xf9, 0x33, 0x7f, 0x78, + 0x44, 0x33, 0xf3, 0x94, 0x5d, 0x74, 0x14, 0x53, + 0x3e, 0xc1, 0xa6, 0x62, 0x3a, 0x94, 0x41, 0xc9, + 0x4d, 0x05, 0x87, 0x7d, 0x92, 0xd9, 0x12, 0xb4, + 0x9a, 0x1f, 0x43, 0xf4, 0x54, 0x0c, 0xb4, 0x6c, + 0xd0, 0x16, 0xd7, 0x46, 0xe2, 0x5e, 0xdc, 0x56, + 0xff, 0x42, 0x72, 0xe4, 0x97, 0x8f, 0xdb, 0x2f, + 0x27, 0xbd, 0x4c, 0xa3, 0x4e, 0x43, 0x4a, 0x0b, + 0x46, 0x45, 0x36, 0x80, 0x0d, 0xd4, 0x87, 0xc7, + 0x1a, 0xf8, 0x5f, 0x9c, 0xf4, 0x10, 0x82, 0xa8, + 0x28, 0xa7, 0xd1, 0xbf, 0xc1, 0x61, 0x5a, 0x73, + 0xbd, 0xe9, 0x44, 0x66, 0x5a, 0x2b, 0x14, 0x4c, + 0xa5, 0x5d, 0x3d, 0x38, 0xfb, 0xd4, 0xa8, 0x24, + 0xbe, 0xe4, 0x99, 0xa1, 0x98, 0x90, 0x72, 0x67, + 0x1f, 0x3b, 0x96, 0xae, 0x60, 0x7a, 0x00, 0xf2, + 0x11, 0x13, 0x9f, 0xc4, 0xb5, 0x63, 0xd7, 0x63, + 0xb6, 0x64, 0xe3, 0xbb, 0xf1, 0x96, 0x9e, 0x77, + 0xab, 0xc4, 0xa8, 0x39, 0xd5, 0x22, 0xe9, 0xee, + 0xad, 0x1f, 0x91, 0xff, 0x56, 0x3e, 0x68, 0x89, + 0x63, 0x11, 0xc8, 0x98, 0xa1, 0x7e, 0xd9, 0x37, + 0xb2, 0x94, 0x23, 0xfb, 0x67, 0xb7, 0xa0, 0xaa, + 0x0f, 0xe7, 0xb6, 0xe1, 0xb8, 0xc3, 0x73, 0xe3, + 0xae, 0x07, 0xe6, 0xf7, 0xc8, 0x35, 0x03, 0xc5, + 0x7a, 0xfc, 0x48, 0xd4, 0xe2, 0x61, 0x7a, 0x22, + 0xdd, 0x78, 0x4b, 0xef, 0xa4, 0xde, 0x27, 0x62, + 0xdd, 0xa1, 0x76, 0xe5, 0xeb, 0x83, 0xa3, 0x18, + 0xde, 0xe9, 0x99, 0x37, 0x66, 0x34, 0x20, 0xaf, + 0x67, 0x2b, 0xdd, 0xa4, 0x69, 0xeb, 0x7d, 0x71, + 0x0f, 0x24, 0xef, 0x88, 0x49, 0x8c, 0xe5, 0x33, + 0xfa, 0xf3, 0x3e, 0xff, 0x46, 0x10, 0x5d, 0x25, + 0x97, 0x7f, 0x8e, 0x00, 0xe2, 0x08, 0x0e, 0x39, + 0x65, 0x4c, 0xa5, 0x1b, 0x5f, 0x5a, 0xa8, 0xab, + 0xb1, 0x4a, 0x55, 0xf0, 0x41, 0x9e, 0xf5, 0xcd, + 0x2c, 0x34, 0x56, 0x11, 0xda, 0x96, 0x68, 0xe4, + 0x39, 0x8d, 0xfe, 0x40, 0xb0, 0x0b, 0x05, 0x5d, + 0xf4, 0xba, 0x27, 0x1a, 0x3b, 0xed, 0xee, 0x88, + 0x07, 0x59, 0x40, 0xf6, 0x6f, 0x44, 0x1a, 0x5f, + 0x3d, 0x42, 0xb2, 0xa7, 0x5d, 0x07, 0xd5, 0x7e, + 0x95, 0x36, 0xc9, 0xa3, 0xd3, 0x45, 0x56, 0x70, + 0x92, 0x79, 0xc9, 0xd7, 0xfd, 0x88, 0xa4, 0x89, + 0x9a, 0x94, 0xbd, 0x9d, 0x49, 0xec, 0x32, 0xc4, + 0xee, 0x87, 0xd7, 0x0a, 0xf8, 0xab, 0x23, 0x70, + 0x3b, 0xbd, 0xd6, 0x34, 0x86, 0x3a, 0x05, 0x68, + 0x95, 0x31, 0x81, 0x2d, 0x6d, 0xde, 0x54, 0xfe, + 0x0b, 0xa9, 0x72, 0x3c, 0x78, 0xb7, 0xf5, 0x84, + 0x67, 0x39, 0x4f, 0x2d, 0xbb, 0xcb, 0x22, 0x2d, + 0xed, 0xf2, 0xc1, 0x56, 0xf8, 0x11, 0xf9, 0xee, + 0x81, 0xd8, 0x64, 0x07, 0xbf, 0xb4, 0x69, 0xdb, + 0xda, 0x0c, 0xf5, 0x20, 0x00, 0xf8, 0x26, 0x7b, + 0x31, 0x54, 0x09, 0x24, 0xbf, 0x7c, 0xf5, 0xad, + 0x76, 0xbb, 0xcc, 0x89, 0xee, 0x5b, 0x2a, 0x23, + 0x12, 0x1c, 0x69, 0x50, 0xdd, 0x03, 0x0d, 0xe4, + 0xca, 0xb8, 0x59, 0x7c, 0x91, 0xa0, 0x82, 0x00, + 0x01, 0x9e, 0x1e, 0x4d, 0x87, 0xf7, 0xab, 0x3d, + 0x06, 0x6c, 0x95, 0x90, 0x63, 0x57, 0x0f, 0x44, + 0x4c, 0x49, 0x21, 0x2e, 0x85, 0x47, 0x61, 0x02, + 0x67, 0x57, 0xdc, 0xde, 0x67, 0x92, 0x11, 0x34, + 0x85, 0x05, 0x9e, 0x25, 0xe4, 0x1b, 0x8e, 0xaa, + 0xca, 0xd9, 0x4c, 0x2c, 0x84, 0x30, 0xf1, 0xdc, + 0x4a, 0x9b, 0x02, 0xdd, 0x69, 0x5e, 0xcd, 0x31, + 0x08, 0x27, 0xd1, 0x83, 0xcd, 0x03, 0x4d, 0xd9, + 0xf0, 0x0a, 0x69, 0x8e, 0x8b, 0x88, 0x14, 0x98, + 0x37, 0x8c, 0xad, 0x93, 0x70, 0x04, 0xf8, 0x88, + 0xa7, 0x67, 0xf0, 0xfe, 0xa9, 0x49, 0x46, 0xbe, + 0xab, 0x14, 0x8c, 0x56, 0xea, 0x17, 0x52, 0x1f, + 0x35, 0xfa, 0xd2, 0xd4, 0xa4, 0xf6, 0xb6, 0x72, + 0x25, 0x03, 0xbf, 0xc1, 0x85, 0xe1, 0x3e, 0x3a, + 0x19, 0xcb, 0xe3, 0x7e, 0x15, 0x65, 0xd1, 0x33, + 0x40, 0x2a, 0xd8, 0x3f, 0x2c, 0x86, 0x12, 0x65, + 0xe2, 0x60, 0x80, 0x1b, 0x01, 0x0b, 0xd2, 0xcd, + 0x3b, 0x24, 0x56, 0x73, 0xcd, 0xa9, 0x34, 0xd1, + 0x36, 0xd3, 0x26, 0x6f, 0x49, 0x58, 0xcf, 0xb7, + 0x39, 0x92, 0xa8, 0x15, 0x47, 0x0f, 0x92, 0x68, + 0x49, 0xa2, 0x91, 0xe0, 0x55, 0xc8, 0xd9, 0xf1, + 0x84, 0xc4, 0x41, 0x67, 0xd9, 0x24, 0xf3, 0x0f, + 0xdc, 0x3d, 0x6d, 0x79, 0x4d, 0x0f, 0x35, 0x8b, + 0xdf, 0x6d, 0xcd, 0x66, 0x7e, 0x82, 0x09, 0xa3, + 0x72, 0x1d, 0x3d, 0x4b, 0x0f, 0xad, 0x7c, 0xbe, + 0xdd, 0x96, 0x17, 0x62, 0x26, 0x72, 0xe6, 0x1d, + 0xb9, 0xf6, 0x9a, 0x71, 0x52, 0x5a, 0x76, 0xbb, + 0x4e, 0x11, 0x78, 0xbe, 0x05, 0xe5, 0xf6, 0xaf, + 0xf2, 0x66, 0xd3, 0xe5, 0xdb, 0xfc, 0xd8, 0x96, + 0x64, 0x8b, 0x7a, 0xec, 0x9f, 0x3e, 0x0d, 0x7c, + 0xd5, 0x20, 0xdf, 0x50, 0x52, 0x57, 0x93, 0xa0, + 0x03, 0x5a, 0xed, 0x5c, 0xb4, 0xfa, 0x15, 0xf0, + 0xda, 0xc4, 0x94, 0xbf, 0xcb, 0x25, 0xc7, 0xda, + 0x59, 0x5d, 0xb8, 0x00, 0x00, 0x00, 0x56, 0x76, + 0xe4, 0x62, 0x1c, 0x71, 0x70, 0xf6, 0x7f, 0x20, + 0x83, 0xee, 0x17, 0x23, 0x56, 0x8c, 0x20, 0x9c, + 0x65, 0x25, 0xe9, 0x38, 0xe2, 0xd2, 0x66, 0xae, + 0xa1, 0x47, 0x16, 0xba, 0x5e, 0x87, 0xd4, 0x8b, + 0x7e, 0x80, 0x9f, 0x83, 0x4b, 0x27, 0x46, 0x97, + 0x72, 0x2b, 0x88, 0xd1, 0xf0, 0x92, 0xd4, 0x2a, + 0x7e, 0x48, 0x63, 0x95, 0x33, 0x13, 0x07, 0xf8, + 0x79, 0x3a, 0x6b, 0x67, 0x1c, 0x6f, 0x38, 0x80, + 0x3c, 0xc6, 0xfa, 0xb8, 0x4e, 0xd2, 0x01, 0xaf, + 0x79, 0x37, 0x60, 0xd6, 0x4d, 0x55, 0xcd, 0x1d, + 0xf5, 0x15, 0x0f, 0xb7, 0x8c, 0xa5, 0xec, 0x25, + 0xe4, 0x45, 0xec, 0xe6, 0xf9, 0xc2, 0x35, 0xea, + 0xc6, 0x30, 0xa2, 0x1f, 0x21, 0x13, 0x1f, 0x97, + 0x95, 0xee, 0x69, 0x63, 0xcf, 0x4b, 0xb2, 0xc3, + 0xc0, 0x23, 0xc9, 0x75, 0x2b, 0xd6, 0xac, 0x3c, + 0xcb, 0x38, 0x73, 0xa0, 0x5a, 0xa5, 0x7d, 0x3d, + 0x23, 0xb1, 0x4c, 0xc9, 0x1b, 0x12, 0xc4, 0x83, + 0xe1, 0x62, 0x61, 0xf3, 0x8c, 0x6a, 0x45, 0x95, + 0xee, 0x74, 0x00, 0x2f, 0x84, 0x77, 0xff, 0x16, + 0x22, 0x02, 0xfe, 0x4b, 0xd2, 0x57, 0x65, 0xee, + 0x49, 0xcd, 0x7b, 0xb5, 0xdb, 0x8e, 0x5a, 0xcb, + 0x70, 0x7f, 0x78, 0xbc, 0x35, 0x34, 0x3e, 0xcd, + 0xf6, 0x24, 0x78, 0x8f, 0xe8, 0x9e, 0x5c, 0x9c, + 0x22, 0x4a, 0xf0, 0xbc, 0x89, 0x64, 0x93, 0xcf, + 0x20, 0xc8, 0xfd, 0x27, 0xe2, 0x36, 0x86, 0x00, + 0x61, 0xe8, 0xe2, 0x9c, 0xad, 0x55, 0x98, 0x77, + 0x2f, 0xfa, 0x28, 0xb4, 0xa7, 0xda, 0xa4, 0x14, + 0x06, 0x8c, 0x7a, 0xd5, 0xdf, 0x0d, 0x32, 0x56, + 0xcc, 0xd3, 0x70, 0x71, 0x70, 0xd5, 0xb6, 0x41, + 0x0f, 0x45, 0xb2, 0xf0, 0x24, 0xa5, 0x23, 0x13, + 0x70, 0x36, 0x07, 0xcd, 0xc6, 0x75, 0xd8, 0x62, + 0x8c, 0x7f, 0xa7, 0xb9, 0x76, 0x16, 0xb3, 0x9a, + 0x7e, 0x20, 0x27, 0x27, 0x2d, 0x33, 0x60, 0x70, + 0xa5, 0xef, 0x5c, 0x9c, 0x6e, 0x5f, 0x2f, 0x20, + 0x78, 0x58, 0x59, 0x92, 0x15, 0xfe, 0x13, 0x07, + 0x87, 0xc7, 0x3e, 0x21, + }, + }, + { + Header: rtp.Header{ + Version: 2, + Marker: true, + PayloadType: 96, + SequenceNumber: 17646, + Timestamp: 2289526357, + SSRC: 0x9dbb7812, + }, + Payload: []byte{ + 0x80, 0xbb, 0x01, 0x04, 0x24, 0x33, 0x60, 0x15, + 0x91, 0xfb, 0xfe, 0xe8, 0xf8, 0xb9, 0xa6, 0x9a, + 0xbf, 0x65, 0xf3, 0x37, 0x40, 0xb8, 0x52, 0x69, + 0x3f, 0x65, 0x27, 0x36, 0x01, 0x92, 0xe8, 0xef, + 0x51, 0x3e, 0xcd, 0xf5, 0xcc, 0x4f, 0x8b, 0x4f, + 0x7b, 0x38, 0x3e, 0x43, 0x4d, 0xc0, 0xa4, 0xc6, + 0x84, 0x79, 0x8e, 0xf4, 0x4a, 0xe1, 0xa9, 0x2b, + 0xd5, 0x34, 0x00, 0x30, 0x94, 0x6a, 0x91, 0xa2, + 0xd5, 0xc0, 0xbf, 0xb5, 0x66, 0x59, 0x38, 0xc2, + 0xa4, 0x75, 0x96, 0x5b, 0x7a, 0xac, 0x9c, 0x05, + 0x67, 0x99, 0x2e, 0xba, 0x21, 0x1e, 0xac, 0x50, + 0x01, 0x68, 0x71, 0xac, 0x68, 0x6d, 0xc1, 0xf2, + 0x2c, 0x51, 0x1e, 0xb6, 0x64, 0x97, 0x3d, 0x9b, + 0x2b, 0x89, 0x66, 0xbd, 0x50, 0x4f, 0x5c, 0xec, + 0x7c, 0xc8, 0x51, 0x61, 0x74, 0xbd, 0x86, 0xb4, + 0x6e, 0x71, 0x59, 0x24, 0x59, 0xaf, 0x66, 0x54, + 0x82, 0xdb, 0xe2, 0x11, 0x6f, 0x87, 0x92, 0xf3, + 0x63, 0xd4, 0x4b, 0xd6, 0x26, 0x42, 0xf1, 0x2a, + 0x66, 0x63, 0x79, 0x5e, 0x7e, 0xfb, 0x3f, 0x85, + 0xa7, 0x24, 0xac, 0x53, 0xe2, 0x57, 0x56, 0xdd, + 0xef, 0x7a, 0xdf, 0xb6, 0x27, 0xaf, 0x25, 0x6a, + 0x89, 0x4a, 0x4c, 0xc3, 0xe6, 0x2e, 0xbe, 0x2b, + 0x38, 0x07, 0xe0, 0x96, 0x98, 0xaf, 0x85, 0xf4, + 0x86, 0x7d, 0xf4, 0xee, 0xe5, 0x78, + }, + }, + }, + }, + { + "aggregated", + [][]byte{shortOBU, shortOBU}, + []*rtp.Packet{ + { + Header: rtp.Header{ + Version: 2, + Marker: true, + PayloadType: 96, + SequenceNumber: 17645, + Timestamp: 2289526357, + SSRC: 0x9dbb7812, + }, + Payload: []byte{ + 0x08, 0x10, 0x0a, 0x0e, 0x00, 0x00, 0x00, 0x4a, + 0xab, 0xbf, 0xc3, 0x77, 0x6b, 0xe4, 0x40, 0x40, + 0x40, 0x41, 0x10, 0x0a, 0x0e, 0x00, 0x00, 0x00, + 0x4a, 0xab, 0xbf, 0xc3, 0x77, 0x6b, 0xe4, 0x40, + 0x40, 0x40, 0x41, + }, + }, + }, + }, + { + "aggregated and fragmented", + [][]byte{shortOBU, longOBU, shortOBU, shortOBU, longOBU, shortOBU}, + []*rtp.Packet{ + { //nolint:dupl + Header: rtp.Header{ + Version: 2, + Marker: false, + PayloadType: 96, + SequenceNumber: 17645, + Timestamp: 2289526357, + SSRC: 0x9dbb7812, + }, + Payload: []byte{ + 0x48, 0x10, 0x0a, 0x0e, 0x00, 0x00, 0x00, 0x4a, + 0xab, 0xbf, 0xc3, 0x77, 0x6b, 0xe4, 0x40, 0x40, + 0x40, 0x41, 0xa0, 0x0b, 0x30, 0x30, 0xca, 0x08, + 0x12, 0xfd, 0xfd, 0x78, 0x89, 0xe5, 0x3e, 0xa3, + 0x80, 0x08, 0x20, 0x82, 0x08, 0x54, 0x50, 0x00, + 0x30, 0x00, 0x00, 0x66, 0x00, 0xeb, 0xcd, 0xc5, + 0x72, 0x25, 0x5a, 0x0a, 0xc3, 0x4a, 0x43, 0x15, + 0x59, 0x13, 0x5f, 0xb9, 0x39, 0x19, 0xf1, 0xca, + 0x26, 0xc7, 0x59, 0xa7, 0x66, 0xe4, 0xa5, 0xff, + 0x3a, 0xba, 0x3f, 0x62, 0xfc, 0x58, 0x07, 0xd0, + 0x18, 0xd6, 0xb2, 0x90, 0x72, 0xf4, 0x57, 0xbd, + 0x5d, 0x72, 0x92, 0x8c, 0x71, 0x48, 0x17, 0x89, + 0x65, 0xa9, 0x9e, 0xa2, 0x81, 0x9a, 0x83, 0x66, + 0x11, 0xd7, 0xe7, 0x41, 0x35, 0xb7, 0x8a, 0xb3, + 0xd0, 0x90, 0x54, 0x2a, 0x48, 0xea, 0x65, 0xd1, + 0xb0, 0x83, 0xda, 0xbb, 0x61, 0xff, 0xc4, 0xd0, + 0x06, 0x78, 0x35, 0xc2, 0xf7, 0x15, 0x16, 0xe5, + 0xc3, 0xf0, 0x9f, 0x7f, 0x1a, 0xd6, 0xad, 0xd4, + 0x41, 0xa4, 0xf4, 0x40, 0x41, 0x00, 0x78, 0x5c, + 0x14, 0x08, 0x57, 0x3d, 0x96, 0xc2, 0x0b, 0xb5, + 0x03, 0xce, 0x7d, 0xe6, 0x50, 0xd1, 0xbc, 0x3e, + 0x1e, 0x84, 0x62, 0x1a, 0xd1, 0xfe, 0x52, 0x9e, + 0x79, 0x26, 0x51, 0xc8, 0x14, 0x54, 0xf2, 0x77, + 0xe6, 0x25, 0x0f, 0x5f, 0xec, 0x66, 0x33, 0xdb, + 0xd0, 0x9f, 0x5a, 0xf9, 0xbc, 0xc4, 0x9b, 0x31, + 0x8c, 0x6f, 0xe6, 0x2a, 0x50, 0x65, 0x1d, 0x45, + 0xaf, 0x19, 0xd4, 0xde, 0xf8, 0x33, 0x43, 0x48, + 0x57, 0x00, 0x80, 0x5b, 0xaa, 0x3e, 0x1b, 0xf7, + 0x21, 0xc1, 0x56, 0x5e, 0xfb, 0xdb, 0x43, 0xa8, + 0x7b, 0xde, 0x82, 0xc1, 0x45, 0x5a, 0x36, 0x04, + 0x20, 0xa8, 0xa3, 0x0b, 0xa9, 0xa8, 0x6d, 0xe1, + 0xfd, 0x13, 0x0d, 0x38, 0xef, 0x00, 0xd5, 0x00, + 0xe5, 0x2d, 0x69, 0x67, 0x17, 0x59, 0xd9, 0xda, + 0x61, 0x95, 0xac, 0x55, 0x3a, 0xc5, 0x77, 0x1e, + 0xbe, 0xa5, 0x58, 0x7a, 0xbb, 0x09, 0xbd, 0x46, + 0xab, 0x82, 0x60, 0x13, 0x8f, 0x8b, 0xfb, 0x29, + 0xe0, 0x7f, 0xa5, 0xca, 0x25, 0xfa, 0x77, 0x07, + 0x88, 0x51, 0xdb, 0xc2, 0x99, 0x5f, 0xad, 0xe1, + 0x45, 0x28, 0x0e, 0x00, 0x86, 0x79, 0x60, 0xe2, + 0x36, 0x9a, 0x41, 0x21, 0x01, 0xdf, 0x3d, 0x0c, + 0x31, 0x37, 0xa4, 0x0b, 0x00, 0xe6, 0x43, 0xfb, + 0x28, 0x05, 0x2c, 0xff, 0x40, 0x1c, 0x23, 0x6d, + 0x4f, 0x58, 0x00, 0xe1, 0xc4, 0xb2, 0x05, 0x3a, + 0x03, 0xa4, 0xde, 0xf4, 0x13, 0x5e, 0x8c, 0x45, + 0xc2, 0x3b, 0xf0, 0x2c, 0x00, 0x28, 0x0b, 0xe2, + 0x7d, 0xa4, 0x27, 0x78, 0xf0, 0xfa, 0x3f, 0x0a, + 0xa9, 0xac, 0x20, 0xa0, 0xe2, 0x33, 0xe8, 0xc6, + 0xa7, 0x69, 0x6f, 0x4c, 0xec, 0x67, 0x06, 0x79, + 0x27, 0x1d, 0x69, 0xe3, 0xa6, 0xad, 0x6e, 0x63, + 0x97, 0xd2, 0xe3, 0xaa, 0xd4, 0xc5, 0x6d, 0xaa, + 0x29, 0xfa, 0xc3, 0x4b, 0x23, 0xec, 0xe7, 0x5f, + 0xdd, 0xf8, 0x45, 0x55, 0x62, 0xec, 0x3c, 0xe8, + 0x73, 0xf0, 0x63, 0x04, 0x6f, 0x88, 0xa7, 0x4d, + 0x7c, 0x28, 0xef, 0x20, 0x0d, 0x00, 0xf9, 0xba, + 0xe5, 0x09, 0x5d, 0xc2, 0x8d, 0x7d, 0x18, 0x2c, + 0x2f, 0xff, 0x93, 0x88, 0x2d, 0x00, 0xf9, 0xaf, + 0x22, 0x68, 0x70, 0x72, 0xe4, 0x36, 0x22, 0x15, + 0x5f, 0x7a, 0xef, 0xd9, 0x03, 0x25, 0xf5, 0x17, + 0x68, 0x30, 0xee, 0x2b, 0xed, 0xe8, 0x0c, 0x1a, + 0x32, 0x72, 0x62, 0xd4, 0x74, 0x69, 0xf1, 0x9a, + 0xcf, 0x9b, 0x52, 0xfc, 0x56, 0xe3, 0xda, 0x73, + 0x09, 0x33, 0x95, 0x08, 0x77, 0x00, 0x09, 0x17, + 0x4d, 0xb7, 0xc4, 0x32, 0xcd, 0xf9, 0x33, 0x7f, + 0x78, 0x44, 0x33, 0xf3, 0x94, 0x5d, 0x74, 0x14, + 0x53, 0x3e, 0xc1, 0xa6, 0x62, 0x3a, 0x94, 0x41, + 0xc9, 0x4d, 0x05, 0x87, 0x7d, 0x92, 0xd9, 0x12, + 0xb4, 0x9a, 0x1f, 0x43, 0xf4, 0x54, 0x0c, 0xb4, + 0x6c, 0xd0, 0x16, 0xd7, 0x46, 0xe2, 0x5e, 0xdc, + 0x56, 0xff, 0x42, 0x72, 0xe4, 0x97, 0x8f, 0xdb, + 0x2f, 0x27, 0xbd, 0x4c, 0xa3, 0x4e, 0x43, 0x4a, + 0x0b, 0x46, 0x45, 0x36, 0x80, 0x0d, 0xd4, 0x87, + 0xc7, 0x1a, 0xf8, 0x5f, 0x9c, 0xf4, 0x10, 0x82, + 0xa8, 0x28, 0xa7, 0xd1, 0xbf, 0xc1, 0x61, 0x5a, + 0x73, 0xbd, 0xe9, 0x44, 0x66, 0x5a, 0x2b, 0x14, + 0x4c, 0xa5, 0x5d, 0x3d, 0x38, 0xfb, 0xd4, 0xa8, + 0x24, 0xbe, 0xe4, 0x99, 0xa1, 0x98, 0x90, 0x72, + 0x67, 0x1f, 0x3b, 0x96, 0xae, 0x60, 0x7a, 0x00, + 0xf2, 0x11, 0x13, 0x9f, 0xc4, 0xb5, 0x63, 0xd7, + 0x63, 0xb6, 0x64, 0xe3, 0xbb, 0xf1, 0x96, 0x9e, + 0x77, 0xab, 0xc4, 0xa8, 0x39, 0xd5, 0x22, 0xe9, + 0xee, 0xad, 0x1f, 0x91, 0xff, 0x56, 0x3e, 0x68, + 0x89, 0x63, 0x11, 0xc8, 0x98, 0xa1, 0x7e, 0xd9, + 0x37, 0xb2, 0x94, 0x23, 0xfb, 0x67, 0xb7, 0xa0, + 0xaa, 0x0f, 0xe7, 0xb6, 0xe1, 0xb8, 0xc3, 0x73, + 0xe3, 0xae, 0x07, 0xe6, 0xf7, 0xc8, 0x35, 0x03, + 0xc5, 0x7a, 0xfc, 0x48, 0xd4, 0xe2, 0x61, 0x7a, + 0x22, 0xdd, 0x78, 0x4b, 0xef, 0xa4, 0xde, 0x27, + 0x62, 0xdd, 0xa1, 0x76, 0xe5, 0xeb, 0x83, 0xa3, + 0x18, 0xde, 0xe9, 0x99, 0x37, 0x66, 0x34, 0x20, + 0xaf, 0x67, 0x2b, 0xdd, 0xa4, 0x69, 0xeb, 0x7d, + 0x71, 0x0f, 0x24, 0xef, 0x88, 0x49, 0x8c, 0xe5, + 0x33, 0xfa, 0xf3, 0x3e, 0xff, 0x46, 0x10, 0x5d, + 0x25, 0x97, 0x7f, 0x8e, 0x00, 0xe2, 0x08, 0x0e, + 0x39, 0x65, 0x4c, 0xa5, 0x1b, 0x5f, 0x5a, 0xa8, + 0xab, 0xb1, 0x4a, 0x55, 0xf0, 0x41, 0x9e, 0xf5, + 0xcd, 0x2c, 0x34, 0x56, 0x11, 0xda, 0x96, 0x68, + 0xe4, 0x39, 0x8d, 0xfe, 0x40, 0xb0, 0x0b, 0x05, + 0x5d, 0xf4, 0xba, 0x27, 0x1a, 0x3b, 0xed, 0xee, + 0x88, 0x07, 0x59, 0x40, 0xf6, 0x6f, 0x44, 0x1a, + 0x5f, 0x3d, 0x42, 0xb2, 0xa7, 0x5d, 0x07, 0xd5, + 0x7e, 0x95, 0x36, 0xc9, 0xa3, 0xd3, 0x45, 0x56, + 0x70, 0x92, 0x79, 0xc9, 0xd7, 0xfd, 0x88, 0xa4, + 0x89, 0x9a, 0x94, 0xbd, 0x9d, 0x49, 0xec, 0x32, + 0xc4, 0xee, 0x87, 0xd7, 0x0a, 0xf8, 0xab, 0x23, + 0x70, 0x3b, 0xbd, 0xd6, 0x34, 0x86, 0x3a, 0x05, + 0x68, 0x95, 0x31, 0x81, 0x2d, 0x6d, 0xde, 0x54, + 0xfe, 0x0b, 0xa9, 0x72, 0x3c, 0x78, 0xb7, 0xf5, + 0x84, 0x67, 0x39, 0x4f, 0x2d, 0xbb, 0xcb, 0x22, + 0x2d, 0xed, 0xf2, 0xc1, 0x56, 0xf8, 0x11, 0xf9, + 0xee, 0x81, 0xd8, 0x64, 0x07, 0xbf, 0xb4, 0x69, + 0xdb, 0xda, 0x0c, 0xf5, 0x20, 0x00, 0xf8, 0x26, + 0x7b, 0x31, 0x54, 0x09, 0x24, 0xbf, 0x7c, 0xf5, + 0xad, 0x76, 0xbb, 0xcc, 0x89, 0xee, 0x5b, 0x2a, + 0x23, 0x12, 0x1c, 0x69, 0x50, 0xdd, 0x03, 0x0d, + 0xe4, 0xca, 0xb8, 0x59, 0x7c, 0x91, 0xa0, 0x82, + 0x00, 0x01, 0x9e, 0x1e, 0x4d, 0x87, 0xf7, 0xab, + 0x3d, 0x06, 0x6c, 0x95, 0x90, 0x63, 0x57, 0x0f, + 0x44, 0x4c, 0x49, 0x21, 0x2e, 0x85, 0x47, 0x61, + 0x02, 0x67, 0x57, 0xdc, 0xde, 0x67, 0x92, 0x11, + 0x34, 0x85, 0x05, 0x9e, 0x25, 0xe4, 0x1b, 0x8e, + 0xaa, 0xca, 0xd9, 0x4c, 0x2c, 0x84, 0x30, 0xf1, + 0xdc, 0x4a, 0x9b, 0x02, 0xdd, 0x69, 0x5e, 0xcd, + 0x31, 0x08, 0x27, 0xd1, 0x83, 0xcd, 0x03, 0x4d, + 0xd9, 0xf0, 0x0a, 0x69, 0x8e, 0x8b, 0x88, 0x14, + 0x98, 0x37, 0x8c, 0xad, 0x93, 0x70, 0x04, 0xf8, + 0x88, 0xa7, 0x67, 0xf0, 0xfe, 0xa9, 0x49, 0x46, + 0xbe, 0xab, 0x14, 0x8c, 0x56, 0xea, 0x17, 0x52, + 0x1f, 0x35, 0xfa, 0xd2, 0xd4, 0xa4, 0xf6, 0xb6, + 0x72, 0x25, 0x03, 0xbf, 0xc1, 0x85, 0xe1, 0x3e, + 0x3a, 0x19, 0xcb, 0xe3, 0x7e, 0x15, 0x65, 0xd1, + 0x33, 0x40, 0x2a, 0xd8, 0x3f, 0x2c, 0x86, 0x12, + 0x65, 0xe2, 0x60, 0x80, 0x1b, 0x01, 0x0b, 0xd2, + 0xcd, 0x3b, 0x24, 0x56, 0x73, 0xcd, 0xa9, 0x34, + 0xd1, 0x36, 0xd3, 0x26, 0x6f, 0x49, 0x58, 0xcf, + 0xb7, 0x39, 0x92, 0xa8, 0x15, 0x47, 0x0f, 0x92, + 0x68, 0x49, 0xa2, 0x91, 0xe0, 0x55, 0xc8, 0xd9, + 0xf1, 0x84, 0xc4, 0x41, 0x67, 0xd9, 0x24, 0xf3, + 0x0f, 0xdc, 0x3d, 0x6d, 0x79, 0x4d, 0x0f, 0x35, + 0x8b, 0xdf, 0x6d, 0xcd, 0x66, 0x7e, 0x82, 0x09, + 0xa3, 0x72, 0x1d, 0x3d, 0x4b, 0x0f, 0xad, 0x7c, + 0xbe, 0xdd, 0x96, 0x17, 0x62, 0x26, 0x72, 0xe6, + 0x1d, 0xb9, 0xf6, 0x9a, 0x71, 0x52, 0x5a, 0x76, + 0xbb, 0x4e, 0x11, 0x78, 0xbe, 0x05, 0xe5, 0xf6, + 0xaf, 0xf2, 0x66, 0xd3, 0xe5, 0xdb, 0xfc, 0xd8, + 0x96, 0x64, 0x8b, 0x7a, 0xec, 0x9f, 0x3e, 0x0d, + 0x7c, 0xd5, 0x20, 0xdf, 0x50, 0x52, 0x57, 0x93, + 0xa0, 0x03, 0x5a, 0xed, 0x5c, 0xb4, 0xfa, 0x15, + 0xf0, 0xda, 0xc4, 0x94, 0xbf, 0xcb, 0x25, 0xc7, + 0xda, 0x59, 0x5d, 0xb8, 0x00, 0x00, 0x00, 0x56, + 0x76, 0xe4, 0x62, 0x1c, 0x71, 0x70, 0xf6, 0x7f, + 0x20, 0x83, 0xee, 0x17, 0x23, 0x56, 0x8c, 0x20, + 0x9c, 0x65, 0x25, 0xe9, 0x38, 0xe2, 0xd2, 0x66, + 0xae, 0xa1, 0x47, 0x16, 0xba, 0x5e, 0x87, 0xd4, + 0x8b, 0x7e, 0x80, 0x9f, 0x83, 0x4b, 0x27, 0x46, + 0x97, 0x72, 0x2b, 0x88, 0xd1, 0xf0, 0x92, 0xd4, + 0x2a, 0x7e, 0x48, 0x63, 0x95, 0x33, 0x13, 0x07, + 0xf8, 0x79, 0x3a, 0x6b, 0x67, 0x1c, 0x6f, 0x38, + 0x80, 0x3c, 0xc6, 0xfa, 0xb8, 0x4e, 0xd2, 0x01, + 0xaf, 0x79, 0x37, 0x60, 0xd6, 0x4d, 0x55, 0xcd, + 0x1d, 0xf5, 0x15, 0x0f, 0xb7, 0x8c, 0xa5, 0xec, + 0x25, 0xe4, 0x45, 0xec, 0xe6, 0xf9, 0xc2, 0x35, + 0xea, 0xc6, 0x30, 0xa2, 0x1f, 0x21, 0x13, 0x1f, + 0x97, 0x95, 0xee, 0x69, 0x63, 0xcf, 0x4b, 0xb2, + 0xc3, 0xc0, 0x23, 0xc9, 0x75, 0x2b, 0xd6, 0xac, + 0x3c, 0xcb, 0x38, 0x73, 0xa0, 0x5a, 0xa5, 0x7d, + 0x3d, 0x23, 0xb1, 0x4c, 0xc9, 0x1b, 0x12, 0xc4, + 0x83, 0xe1, 0x62, 0x61, 0xf3, 0x8c, 0x6a, 0x45, + 0x95, 0xee, 0x74, 0x00, 0x2f, 0x84, 0x77, 0xff, + 0x16, 0x22, 0x02, 0xfe, 0x4b, 0xd2, 0x57, 0x65, + 0xee, 0x49, 0xcd, 0x7b, 0xb5, 0xdb, 0x8e, 0x5a, + 0xcb, 0x70, 0x7f, 0x78, 0xbc, 0x35, 0x34, 0x3e, + 0xcd, 0xf6, 0x24, 0x78, 0x8f, 0xe8, 0x9e, 0x5c, + 0x9c, 0x22, 0x4a, 0xf0, 0xbc, 0x89, 0x64, 0x93, + 0xcf, 0x20, 0xc8, 0xfd, 0x27, 0xe2, 0x36, 0x86, + 0x00, 0x61, 0xe8, 0xe2, 0x9c, 0xad, 0x55, 0x98, + 0x77, 0x2f, 0xfa, 0x28, 0xb4, 0xa7, 0xda, 0xa4, + 0x14, 0x06, 0x8c, 0x7a, 0xd5, 0xdf, 0x0d, 0x32, + 0x56, 0xcc, 0xd3, 0x70, 0x71, 0x70, 0xd5, 0xb6, + 0x41, 0x0f, 0x45, 0xb2, 0xf0, 0x24, 0xa5, 0x23, + 0x13, 0x70, 0x36, 0x07, 0xcd, 0xc6, 0x75, 0xd8, + 0x62, 0x8c, 0x7f, 0xa7, 0xb9, 0x76, 0x16, 0xb3, + 0x9a, 0x7e, 0x20, 0x27, 0x27, 0x2d, 0x33, 0x60, + 0x70, 0xa5, 0xef, 0x5c, + }, + }, + { //nolint:dupl + Header: rtp.Header{ + Version: 2, + Marker: false, + PayloadType: 96, + SequenceNumber: 17646, + Timestamp: 2289526357, + SSRC: 0x9dbb7812, + }, + Payload: []byte{ + 0xc0, 0xcc, 0x01, 0x9c, 0x6e, 0x5f, 0x2f, 0x20, + 0x78, 0x58, 0x59, 0x92, 0x15, 0xfe, 0x13, 0x07, + 0x87, 0xc7, 0x3e, 0x21, 0x04, 0x24, 0x33, 0x60, + 0x15, 0x91, 0xfb, 0xfe, 0xe8, 0xf8, 0xb9, 0xa6, + 0x9a, 0xbf, 0x65, 0xf3, 0x37, 0x40, 0xb8, 0x52, + 0x69, 0x3f, 0x65, 0x27, 0x36, 0x01, 0x92, 0xe8, + 0xef, 0x51, 0x3e, 0xcd, 0xf5, 0xcc, 0x4f, 0x8b, + 0x4f, 0x7b, 0x38, 0x3e, 0x43, 0x4d, 0xc0, 0xa4, + 0xc6, 0x84, 0x79, 0x8e, 0xf4, 0x4a, 0xe1, 0xa9, + 0x2b, 0xd5, 0x34, 0x00, 0x30, 0x94, 0x6a, 0x91, + 0xa2, 0xd5, 0xc0, 0xbf, 0xb5, 0x66, 0x59, 0x38, + 0xc2, 0xa4, 0x75, 0x96, 0x5b, 0x7a, 0xac, 0x9c, + 0x05, 0x67, 0x99, 0x2e, 0xba, 0x21, 0x1e, 0xac, + 0x50, 0x01, 0x68, 0x71, 0xac, 0x68, 0x6d, 0xc1, + 0xf2, 0x2c, 0x51, 0x1e, 0xb6, 0x64, 0x97, 0x3d, + 0x9b, 0x2b, 0x89, 0x66, 0xbd, 0x50, 0x4f, 0x5c, + 0xec, 0x7c, 0xc8, 0x51, 0x61, 0x74, 0xbd, 0x86, + 0xb4, 0x6e, 0x71, 0x59, 0x24, 0x59, 0xaf, 0x66, + 0x54, 0x82, 0xdb, 0xe2, 0x11, 0x6f, 0x87, 0x92, + 0xf3, 0x63, 0xd4, 0x4b, 0xd6, 0x26, 0x42, 0xf1, + 0x2a, 0x66, 0x63, 0x79, 0x5e, 0x7e, 0xfb, 0x3f, + 0x85, 0xa7, 0x24, 0xac, 0x53, 0xe2, 0x57, 0x56, + 0xdd, 0xef, 0x7a, 0xdf, 0xb6, 0x27, 0xaf, 0x25, + 0x6a, 0x89, 0x4a, 0x4c, 0xc3, 0xe6, 0x2e, 0xbe, + 0x2b, 0x38, 0x07, 0xe0, 0x96, 0x98, 0xaf, 0x85, + 0xf4, 0x86, 0x7d, 0xf4, 0xee, 0xe5, 0x78, 0x10, + 0x0a, 0x0e, 0x00, 0x00, 0x00, 0x4a, 0xab, 0xbf, + 0xc3, 0x77, 0x6b, 0xe4, 0x40, 0x40, 0x40, 0x41, + 0x10, 0x0a, 0x0e, 0x00, 0x00, 0x00, 0x4a, 0xab, + 0xbf, 0xc3, 0x77, 0x6b, 0xe4, 0x40, 0x40, 0x40, + 0x41, 0xc1, 0x09, 0x30, 0x30, 0xca, 0x08, 0x12, + 0xfd, 0xfd, 0x78, 0x89, 0xe5, 0x3e, 0xa3, 0x80, + 0x08, 0x20, 0x82, 0x08, 0x54, 0x50, 0x00, 0x30, + 0x00, 0x00, 0x66, 0x00, 0xeb, 0xcd, 0xc5, 0x72, + 0x25, 0x5a, 0x0a, 0xc3, 0x4a, 0x43, 0x15, 0x59, + 0x13, 0x5f, 0xb9, 0x39, 0x19, 0xf1, 0xca, 0x26, + 0xc7, 0x59, 0xa7, 0x66, 0xe4, 0xa5, 0xff, 0x3a, + 0xba, 0x3f, 0x62, 0xfc, 0x58, 0x07, 0xd0, 0x18, + 0xd6, 0xb2, 0x90, 0x72, 0xf4, 0x57, 0xbd, 0x5d, + 0x72, 0x92, 0x8c, 0x71, 0x48, 0x17, 0x89, 0x65, + 0xa9, 0x9e, 0xa2, 0x81, 0x9a, 0x83, 0x66, 0x11, + 0xd7, 0xe7, 0x41, 0x35, 0xb7, 0x8a, 0xb3, 0xd0, + 0x90, 0x54, 0x2a, 0x48, 0xea, 0x65, 0xd1, 0xb0, + 0x83, 0xda, 0xbb, 0x61, 0xff, 0xc4, 0xd0, 0x06, + 0x78, 0x35, 0xc2, 0xf7, 0x15, 0x16, 0xe5, 0xc3, + 0xf0, 0x9f, 0x7f, 0x1a, 0xd6, 0xad, 0xd4, 0x41, + 0xa4, 0xf4, 0x40, 0x41, 0x00, 0x78, 0x5c, 0x14, + 0x08, 0x57, 0x3d, 0x96, 0xc2, 0x0b, 0xb5, 0x03, + 0xce, 0x7d, 0xe6, 0x50, 0xd1, 0xbc, 0x3e, 0x1e, + 0x84, 0x62, 0x1a, 0xd1, 0xfe, 0x52, 0x9e, 0x79, + 0x26, 0x51, 0xc8, 0x14, 0x54, 0xf2, 0x77, 0xe6, + 0x25, 0x0f, 0x5f, 0xec, 0x66, 0x33, 0xdb, 0xd0, + 0x9f, 0x5a, 0xf9, 0xbc, 0xc4, 0x9b, 0x31, 0x8c, + 0x6f, 0xe6, 0x2a, 0x50, 0x65, 0x1d, 0x45, 0xaf, + 0x19, 0xd4, 0xde, 0xf8, 0x33, 0x43, 0x48, 0x57, + 0x00, 0x80, 0x5b, 0xaa, 0x3e, 0x1b, 0xf7, 0x21, + 0xc1, 0x56, 0x5e, 0xfb, 0xdb, 0x43, 0xa8, 0x7b, + 0xde, 0x82, 0xc1, 0x45, 0x5a, 0x36, 0x04, 0x20, + 0xa8, 0xa3, 0x0b, 0xa9, 0xa8, 0x6d, 0xe1, 0xfd, + 0x13, 0x0d, 0x38, 0xef, 0x00, 0xd5, 0x00, 0xe5, + 0x2d, 0x69, 0x67, 0x17, 0x59, 0xd9, 0xda, 0x61, + 0x95, 0xac, 0x55, 0x3a, 0xc5, 0x77, 0x1e, 0xbe, + 0xa5, 0x58, 0x7a, 0xbb, 0x09, 0xbd, 0x46, 0xab, + 0x82, 0x60, 0x13, 0x8f, 0x8b, 0xfb, 0x29, 0xe0, + 0x7f, 0xa5, 0xca, 0x25, 0xfa, 0x77, 0x07, 0x88, + 0x51, 0xdb, 0xc2, 0x99, 0x5f, 0xad, 0xe1, 0x45, + 0x28, 0x0e, 0x00, 0x86, 0x79, 0x60, 0xe2, 0x36, + 0x9a, 0x41, 0x21, 0x01, 0xdf, 0x3d, 0x0c, 0x31, + 0x37, 0xa4, 0x0b, 0x00, 0xe6, 0x43, 0xfb, 0x28, + 0x05, 0x2c, 0xff, 0x40, 0x1c, 0x23, 0x6d, 0x4f, + 0x58, 0x00, 0xe1, 0xc4, 0xb2, 0x05, 0x3a, 0x03, + 0xa4, 0xde, 0xf4, 0x13, 0x5e, 0x8c, 0x45, 0xc2, + 0x3b, 0xf0, 0x2c, 0x00, 0x28, 0x0b, 0xe2, 0x7d, + 0xa4, 0x27, 0x78, 0xf0, 0xfa, 0x3f, 0x0a, 0xa9, + 0xac, 0x20, 0xa0, 0xe2, 0x33, 0xe8, 0xc6, 0xa7, + 0x69, 0x6f, 0x4c, 0xec, 0x67, 0x06, 0x79, 0x27, + 0x1d, 0x69, 0xe3, 0xa6, 0xad, 0x6e, 0x63, 0x97, + 0xd2, 0xe3, 0xaa, 0xd4, 0xc5, 0x6d, 0xaa, 0x29, + 0xfa, 0xc3, 0x4b, 0x23, 0xec, 0xe7, 0x5f, 0xdd, + 0xf8, 0x45, 0x55, 0x62, 0xec, 0x3c, 0xe8, 0x73, + 0xf0, 0x63, 0x04, 0x6f, 0x88, 0xa7, 0x4d, 0x7c, + 0x28, 0xef, 0x20, 0x0d, 0x00, 0xf9, 0xba, 0xe5, + 0x09, 0x5d, 0xc2, 0x8d, 0x7d, 0x18, 0x2c, 0x2f, + 0xff, 0x93, 0x88, 0x2d, 0x00, 0xf9, 0xaf, 0x22, + 0x68, 0x70, 0x72, 0xe4, 0x36, 0x22, 0x15, 0x5f, + 0x7a, 0xef, 0xd9, 0x03, 0x25, 0xf5, 0x17, 0x68, + 0x30, 0xee, 0x2b, 0xed, 0xe8, 0x0c, 0x1a, 0x32, + 0x72, 0x62, 0xd4, 0x74, 0x69, 0xf1, 0x9a, 0xcf, + 0x9b, 0x52, 0xfc, 0x56, 0xe3, 0xda, 0x73, 0x09, + 0x33, 0x95, 0x08, 0x77, 0x00, 0x09, 0x17, 0x4d, + 0xb7, 0xc4, 0x32, 0xcd, 0xf9, 0x33, 0x7f, 0x78, + 0x44, 0x33, 0xf3, 0x94, 0x5d, 0x74, 0x14, 0x53, + 0x3e, 0xc1, 0xa6, 0x62, 0x3a, 0x94, 0x41, 0xc9, + 0x4d, 0x05, 0x87, 0x7d, 0x92, 0xd9, 0x12, 0xb4, + 0x9a, 0x1f, 0x43, 0xf4, 0x54, 0x0c, 0xb4, 0x6c, + 0xd0, 0x16, 0xd7, 0x46, 0xe2, 0x5e, 0xdc, 0x56, + 0xff, 0x42, 0x72, 0xe4, 0x97, 0x8f, 0xdb, 0x2f, + 0x27, 0xbd, 0x4c, 0xa3, 0x4e, 0x43, 0x4a, 0x0b, + 0x46, 0x45, 0x36, 0x80, 0x0d, 0xd4, 0x87, 0xc7, + 0x1a, 0xf8, 0x5f, 0x9c, 0xf4, 0x10, 0x82, 0xa8, + 0x28, 0xa7, 0xd1, 0xbf, 0xc1, 0x61, 0x5a, 0x73, + 0xbd, 0xe9, 0x44, 0x66, 0x5a, 0x2b, 0x14, 0x4c, + 0xa5, 0x5d, 0x3d, 0x38, 0xfb, 0xd4, 0xa8, 0x24, + 0xbe, 0xe4, 0x99, 0xa1, 0x98, 0x90, 0x72, 0x67, + 0x1f, 0x3b, 0x96, 0xae, 0x60, 0x7a, 0x00, 0xf2, + 0x11, 0x13, 0x9f, 0xc4, 0xb5, 0x63, 0xd7, 0x63, + 0xb6, 0x64, 0xe3, 0xbb, 0xf1, 0x96, 0x9e, 0x77, + 0xab, 0xc4, 0xa8, 0x39, 0xd5, 0x22, 0xe9, 0xee, + 0xad, 0x1f, 0x91, 0xff, 0x56, 0x3e, 0x68, 0x89, + 0x63, 0x11, 0xc8, 0x98, 0xa1, 0x7e, 0xd9, 0x37, + 0xb2, 0x94, 0x23, 0xfb, 0x67, 0xb7, 0xa0, 0xaa, + 0x0f, 0xe7, 0xb6, 0xe1, 0xb8, 0xc3, 0x73, 0xe3, + 0xae, 0x07, 0xe6, 0xf7, 0xc8, 0x35, 0x03, 0xc5, + 0x7a, 0xfc, 0x48, 0xd4, 0xe2, 0x61, 0x7a, 0x22, + 0xdd, 0x78, 0x4b, 0xef, 0xa4, 0xde, 0x27, 0x62, + 0xdd, 0xa1, 0x76, 0xe5, 0xeb, 0x83, 0xa3, 0x18, + 0xde, 0xe9, 0x99, 0x37, 0x66, 0x34, 0x20, 0xaf, + 0x67, 0x2b, 0xdd, 0xa4, 0x69, 0xeb, 0x7d, 0x71, + 0x0f, 0x24, 0xef, 0x88, 0x49, 0x8c, 0xe5, 0x33, + 0xfa, 0xf3, 0x3e, 0xff, 0x46, 0x10, 0x5d, 0x25, + 0x97, 0x7f, 0x8e, 0x00, 0xe2, 0x08, 0x0e, 0x39, + 0x65, 0x4c, 0xa5, 0x1b, 0x5f, 0x5a, 0xa8, 0xab, + 0xb1, 0x4a, 0x55, 0xf0, 0x41, 0x9e, 0xf5, 0xcd, + 0x2c, 0x34, 0x56, 0x11, 0xda, 0x96, 0x68, 0xe4, + 0x39, 0x8d, 0xfe, 0x40, 0xb0, 0x0b, 0x05, 0x5d, + 0xf4, 0xba, 0x27, 0x1a, 0x3b, 0xed, 0xee, 0x88, + 0x07, 0x59, 0x40, 0xf6, 0x6f, 0x44, 0x1a, 0x5f, + 0x3d, 0x42, 0xb2, 0xa7, 0x5d, 0x07, 0xd5, 0x7e, + 0x95, 0x36, 0xc9, 0xa3, 0xd3, 0x45, 0x56, 0x70, + 0x92, 0x79, 0xc9, 0xd7, 0xfd, 0x88, 0xa4, 0x89, + 0x9a, 0x94, 0xbd, 0x9d, 0x49, 0xec, 0x32, 0xc4, + 0xee, 0x87, 0xd7, 0x0a, 0xf8, 0xab, 0x23, 0x70, + 0x3b, 0xbd, 0xd6, 0x34, 0x86, 0x3a, 0x05, 0x68, + 0x95, 0x31, 0x81, 0x2d, 0x6d, 0xde, 0x54, 0xfe, + 0x0b, 0xa9, 0x72, 0x3c, 0x78, 0xb7, 0xf5, 0x84, + 0x67, 0x39, 0x4f, 0x2d, 0xbb, 0xcb, 0x22, 0x2d, + 0xed, 0xf2, 0xc1, 0x56, 0xf8, 0x11, 0xf9, 0xee, + 0x81, 0xd8, 0x64, 0x07, 0xbf, 0xb4, 0x69, 0xdb, + 0xda, 0x0c, 0xf5, 0x20, 0x00, 0xf8, 0x26, 0x7b, + 0x31, 0x54, 0x09, 0x24, 0xbf, 0x7c, 0xf5, 0xad, + 0x76, 0xbb, 0xcc, 0x89, 0xee, 0x5b, 0x2a, 0x23, + 0x12, 0x1c, 0x69, 0x50, 0xdd, 0x03, 0x0d, 0xe4, + 0xca, 0xb8, 0x59, 0x7c, 0x91, 0xa0, 0x82, 0x00, + 0x01, 0x9e, 0x1e, 0x4d, 0x87, 0xf7, 0xab, 0x3d, + 0x06, 0x6c, 0x95, 0x90, 0x63, 0x57, 0x0f, 0x44, + 0x4c, 0x49, 0x21, 0x2e, 0x85, 0x47, 0x61, 0x02, + 0x67, 0x57, 0xdc, 0xde, 0x67, 0x92, 0x11, 0x34, + 0x85, 0x05, 0x9e, 0x25, 0xe4, 0x1b, 0x8e, 0xaa, + 0xca, 0xd9, 0x4c, 0x2c, 0x84, 0x30, 0xf1, 0xdc, + 0x4a, 0x9b, 0x02, 0xdd, 0x69, 0x5e, 0xcd, 0x31, + 0x08, 0x27, 0xd1, 0x83, 0xcd, 0x03, 0x4d, 0xd9, + 0xf0, 0x0a, 0x69, 0x8e, 0x8b, 0x88, 0x14, 0x98, + 0x37, 0x8c, 0xad, 0x93, 0x70, 0x04, 0xf8, 0x88, + 0xa7, 0x67, 0xf0, 0xfe, 0xa9, 0x49, 0x46, 0xbe, + 0xab, 0x14, 0x8c, 0x56, 0xea, 0x17, 0x52, 0x1f, + 0x35, 0xfa, 0xd2, 0xd4, 0xa4, 0xf6, 0xb6, 0x72, + 0x25, 0x03, 0xbf, 0xc1, 0x85, 0xe1, 0x3e, 0x3a, + 0x19, 0xcb, 0xe3, 0x7e, 0x15, 0x65, 0xd1, 0x33, + 0x40, 0x2a, 0xd8, 0x3f, 0x2c, 0x86, 0x12, 0x65, + 0xe2, 0x60, 0x80, 0x1b, 0x01, 0x0b, 0xd2, 0xcd, + 0x3b, 0x24, 0x56, 0x73, 0xcd, 0xa9, 0x34, 0xd1, + 0x36, 0xd3, 0x26, 0x6f, 0x49, 0x58, 0xcf, 0xb7, + 0x39, 0x92, 0xa8, 0x15, 0x47, 0x0f, 0x92, 0x68, + 0x49, 0xa2, 0x91, 0xe0, 0x55, 0xc8, 0xd9, 0xf1, + 0x84, 0xc4, 0x41, 0x67, 0xd9, 0x24, 0xf3, 0x0f, + 0xdc, 0x3d, 0x6d, 0x79, 0x4d, 0x0f, 0x35, 0x8b, + 0xdf, 0x6d, 0xcd, 0x66, 0x7e, 0x82, 0x09, 0xa3, + 0x72, 0x1d, 0x3d, 0x4b, 0x0f, 0xad, 0x7c, 0xbe, + 0xdd, 0x96, 0x17, 0x62, 0x26, 0x72, 0xe6, 0x1d, + 0xb9, 0xf6, 0x9a, 0x71, 0x52, 0x5a, 0x76, 0xbb, + 0x4e, 0x11, 0x78, 0xbe, 0x05, 0xe5, 0xf6, 0xaf, + 0xf2, 0x66, 0xd3, 0xe5, 0xdb, 0xfc, 0xd8, 0x96, + 0x64, 0x8b, 0x7a, 0xec, 0x9f, 0x3e, 0x0d, 0x7c, + 0xd5, 0x20, 0xdf, 0x50, 0x52, 0x57, 0x93, 0xa0, + 0x03, 0x5a, 0xed, 0x5c, 0xb4, 0xfa, 0x15, 0xf0, + 0xda, 0xc4, 0x94, 0xbf, 0xcb, 0x25, 0xc7, 0xda, + 0x59, 0x5d, 0xb8, 0x00, 0x00, 0x00, 0x56, 0x76, + 0xe4, 0x62, 0x1c, 0x71, 0x70, 0xf6, 0x7f, 0x20, + 0x83, 0xee, 0x17, 0x23, 0x56, 0x8c, 0x20, 0x9c, + 0x65, 0x25, 0xe9, 0x38, 0xe2, 0xd2, 0x66, 0xae, + 0xa1, 0x47, 0x16, 0xba, 0x5e, 0x87, 0xd4, 0x8b, + 0x7e, 0x80, 0x9f, 0x83, 0x4b, 0x27, 0x46, 0x97, + 0x72, 0x2b, 0x88, 0xd1, + }, + }, + { + Header: rtp.Header{ + Version: 2, + Marker: true, + PayloadType: 96, + SequenceNumber: 17647, + Timestamp: 2289526357, + SSRC: 0x9dbb7812, + }, + Payload: []byte{ + 0x80, 0xab, 0x03, 0xf0, 0x92, 0xd4, 0x2a, 0x7e, + 0x48, 0x63, 0x95, 0x33, 0x13, 0x07, 0xf8, 0x79, + 0x3a, 0x6b, 0x67, 0x1c, 0x6f, 0x38, 0x80, 0x3c, + 0xc6, 0xfa, 0xb8, 0x4e, 0xd2, 0x01, 0xaf, 0x79, + 0x37, 0x60, 0xd6, 0x4d, 0x55, 0xcd, 0x1d, 0xf5, + 0x15, 0x0f, 0xb7, 0x8c, 0xa5, 0xec, 0x25, 0xe4, + 0x45, 0xec, 0xe6, 0xf9, 0xc2, 0x35, 0xea, 0xc6, + 0x30, 0xa2, 0x1f, 0x21, 0x13, 0x1f, 0x97, 0x95, + 0xee, 0x69, 0x63, 0xcf, 0x4b, 0xb2, 0xc3, 0xc0, + 0x23, 0xc9, 0x75, 0x2b, 0xd6, 0xac, 0x3c, 0xcb, + 0x38, 0x73, 0xa0, 0x5a, 0xa5, 0x7d, 0x3d, 0x23, + 0xb1, 0x4c, 0xc9, 0x1b, 0x12, 0xc4, 0x83, 0xe1, + 0x62, 0x61, 0xf3, 0x8c, 0x6a, 0x45, 0x95, 0xee, + 0x74, 0x00, 0x2f, 0x84, 0x77, 0xff, 0x16, 0x22, + 0x02, 0xfe, 0x4b, 0xd2, 0x57, 0x65, 0xee, 0x49, + 0xcd, 0x7b, 0xb5, 0xdb, 0x8e, 0x5a, 0xcb, 0x70, + 0x7f, 0x78, 0xbc, 0x35, 0x34, 0x3e, 0xcd, 0xf6, + 0x24, 0x78, 0x8f, 0xe8, 0x9e, 0x5c, 0x9c, 0x22, + 0x4a, 0xf0, 0xbc, 0x89, 0x64, 0x93, 0xcf, 0x20, + 0xc8, 0xfd, 0x27, 0xe2, 0x36, 0x86, 0x00, 0x61, + 0xe8, 0xe2, 0x9c, 0xad, 0x55, 0x98, 0x77, 0x2f, + 0xfa, 0x28, 0xb4, 0xa7, 0xda, 0xa4, 0x14, 0x06, + 0x8c, 0x7a, 0xd5, 0xdf, 0x0d, 0x32, 0x56, 0xcc, + 0xd3, 0x70, 0x71, 0x70, 0xd5, 0xb6, 0x41, 0x0f, + 0x45, 0xb2, 0xf0, 0x24, 0xa5, 0x23, 0x13, 0x70, + 0x36, 0x07, 0xcd, 0xc6, 0x75, 0xd8, 0x62, 0x8c, + 0x7f, 0xa7, 0xb9, 0x76, 0x16, 0xb3, 0x9a, 0x7e, + 0x20, 0x27, 0x27, 0x2d, 0x33, 0x60, 0x70, 0xa5, + 0xef, 0x5c, 0x9c, 0x6e, 0x5f, 0x2f, 0x20, 0x78, + 0x58, 0x59, 0x92, 0x15, 0xfe, 0x13, 0x07, 0x87, + 0xc7, 0x3e, 0x21, 0x04, 0x24, 0x33, 0x60, 0x15, + 0x91, 0xfb, 0xfe, 0xe8, 0xf8, 0xb9, 0xa6, 0x9a, + 0xbf, 0x65, 0xf3, 0x37, 0x40, 0xb8, 0x52, 0x69, + 0x3f, 0x65, 0x27, 0x36, 0x01, 0x92, 0xe8, 0xef, + 0x51, 0x3e, 0xcd, 0xf5, 0xcc, 0x4f, 0x8b, 0x4f, + 0x7b, 0x38, 0x3e, 0x43, 0x4d, 0xc0, 0xa4, 0xc6, + 0x84, 0x79, 0x8e, 0xf4, 0x4a, 0xe1, 0xa9, 0x2b, + 0xd5, 0x34, 0x00, 0x30, 0x94, 0x6a, 0x91, 0xa2, + 0xd5, 0xc0, 0xbf, 0xb5, 0x66, 0x59, 0x38, 0xc2, + 0xa4, 0x75, 0x96, 0x5b, 0x7a, 0xac, 0x9c, 0x05, + 0x67, 0x99, 0x2e, 0xba, 0x21, 0x1e, 0xac, 0x50, + 0x01, 0x68, 0x71, 0xac, 0x68, 0x6d, 0xc1, 0xf2, + 0x2c, 0x51, 0x1e, 0xb6, 0x64, 0x97, 0x3d, 0x9b, + 0x2b, 0x89, 0x66, 0xbd, 0x50, 0x4f, 0x5c, 0xec, + 0x7c, 0xc8, 0x51, 0x61, 0x74, 0xbd, 0x86, 0xb4, + 0x6e, 0x71, 0x59, 0x24, 0x59, 0xaf, 0x66, 0x54, + 0x82, 0xdb, 0xe2, 0x11, 0x6f, 0x87, 0x92, 0xf3, + 0x63, 0xd4, 0x4b, 0xd6, 0x26, 0x42, 0xf1, 0x2a, + 0x66, 0x63, 0x79, 0x5e, 0x7e, 0xfb, 0x3f, 0x85, + 0xa7, 0x24, 0xac, 0x53, 0xe2, 0x57, 0x56, 0xdd, + 0xef, 0x7a, 0xdf, 0xb6, 0x27, 0xaf, 0x25, 0x6a, + 0x89, 0x4a, 0x4c, 0xc3, 0xe6, 0x2e, 0xbe, 0x2b, + 0x38, 0x07, 0xe0, 0x96, 0x98, 0xaf, 0x85, 0xf4, + 0x86, 0x7d, 0xf4, 0xee, 0xe5, 0x78, 0x10, 0x0a, + 0x0e, 0x00, 0x00, 0x00, 0x4a, 0xab, 0xbf, 0xc3, + 0x77, 0x6b, 0xe4, 0x40, 0x40, 0x40, 0x41, + }, + }, + }, + }, +} + +func TestEncode(t *testing.T) { + for _, ca := range cases { + t.Run(ca.name, func(t *testing.T) { + e := &Encoder{ + PayloadType: 96, + SSRC: func() *uint32 { + v := uint32(0x9dbb7812) + return &v + }(), + InitialSequenceNumber: func() *uint16 { + v := uint16(0x44ed) + return &v + }(), + InitialTimestamp: func() *uint32 { + v := uint32(0x88776655) + return &v + }(), + } + e.Init() + + pkts, err := e.Encode(ca.obus, 0) + require.NoError(t, err) + require.Equal(t, ca.pkts, pkts) + }) + } +} + +func TestEncodeRandomInitialState(t *testing.T) { + e := &Encoder{ + PayloadType: 96, + } + e.Init() + require.NotEqual(t, nil, e.SSRC) + require.NotEqual(t, nil, e.InitialSequenceNumber) + require.NotEqual(t, nil, e.InitialTimestamp) +} diff --git a/pkg/formats/rtpav1/rtpav1.go b/pkg/formats/rtpav1/rtpav1.go new file mode 100644 index 00000000..161b1aff --- /dev/null +++ b/pkg/formats/rtpav1/rtpav1.go @@ -0,0 +1,2 @@ +// Package rtpav1 contains a RTP/AV1 decoder and encoder. +package rtpav1 diff --git a/pkg/formats/rtpav1/testdata/fuzz/FuzzDecoder/079a435e5445c35b b/pkg/formats/rtpav1/testdata/fuzz/FuzzDecoder/079a435e5445c35b new file mode 100644 index 00000000..bd06f9a9 --- /dev/null +++ b/pkg/formats/rtpav1/testdata/fuzz/FuzzDecoder/079a435e5445c35b @@ -0,0 +1,5 @@ +go test fuzz v1 +[]byte("") +bool(false) +[]byte("") +bool(false) diff --git a/pkg/formats/rtpav1/testdata/fuzz/FuzzDecoder/1bcf1d62b055a123 b/pkg/formats/rtpav1/testdata/fuzz/FuzzDecoder/1bcf1d62b055a123 new file mode 100644 index 00000000..2f9ecb9a --- /dev/null +++ b/pkg/formats/rtpav1/testdata/fuzz/FuzzDecoder/1bcf1d62b055a123 @@ -0,0 +1,5 @@ +go test fuzz v1 +[]byte("\x190") +bool(false) +[]byte("\xd00") +bool(false) diff --git a/pkg/formats/rtpav1/testdata/fuzz/FuzzDecoder/894f7b51b885dbb1 b/pkg/formats/rtpav1/testdata/fuzz/FuzzDecoder/894f7b51b885dbb1 new file mode 100644 index 00000000..fb553a64 --- /dev/null +++ b/pkg/formats/rtpav1/testdata/fuzz/FuzzDecoder/894f7b51b885dbb1 @@ -0,0 +1,5 @@ +go test fuzz v1 +[]byte("0\x00") +bool(true) +[]byte("0") +bool(false) diff --git a/pkg/formats/rtpav1/testdata/fuzz/FuzzDecoder/bf1e5b208e57f701 b/pkg/formats/rtpav1/testdata/fuzz/FuzzDecoder/bf1e5b208e57f701 new file mode 100644 index 00000000..e175acef --- /dev/null +++ b/pkg/formats/rtpav1/testdata/fuzz/FuzzDecoder/bf1e5b208e57f701 @@ -0,0 +1,5 @@ +go test fuzz v1 +[]byte("\xd00") +bool(false) +[]byte("") +bool(false) diff --git a/pkg/formats/rtph264/decoder.go b/pkg/formats/rtph264/decoder.go index f7b48d83..9137ad90 100644 --- a/pkg/formats/rtph264/decoder.go +++ b/pkg/formats/rtph264/decoder.go @@ -39,7 +39,7 @@ type Decoder struct { timeDecoder *rtptime.Decoder firstPacketReceived bool - fragmentedSize int + fragmentsSize int fragments [][]byte annexBMode bool @@ -59,7 +59,7 @@ func (d *Decoder) Decode(pkt *rtp.Packet) ([][]byte, time.Duration, error) { } if len(pkt.Payload) < 1 { - d.fragments = d.fragments[:0] // discard pending fragmented packets + d.fragments = d.fragments[:0] // discard pending fragments return nil, 0, fmt.Errorf("payload is too short") } @@ -76,7 +76,7 @@ func (d *Decoder) Decode(pkt *rtp.Packet) ([][]byte, time.Duration, error) { end := (pkt.Payload[1] >> 6) & 0x01 if start == 1 { - d.fragments = d.fragments[:0] // discard pending fragmented packets + d.fragments = d.fragments[:0] // discard pending fragments if end != 0 { return nil, 0, fmt.Errorf("invalid FU-A packet (can't contain both a start and end bit)") @@ -84,7 +84,7 @@ func (d *Decoder) Decode(pkt *rtp.Packet) ([][]byte, time.Duration, error) { nri := (pkt.Payload[0] >> 5) & 0x03 typ := pkt.Payload[1] & 0x1F - d.fragmentedSize = len(pkt.Payload[1:]) + d.fragmentsSize = len(pkt.Payload[1:]) d.fragments = append(d.fragments, []byte{(nri << 5) | typ}, pkt.Payload[2:]) d.firstPacketReceived = true @@ -99,10 +99,10 @@ func (d *Decoder) Decode(pkt *rtp.Packet) ([][]byte, time.Duration, error) { return nil, 0, fmt.Errorf("invalid FU-A packet (non-starting)") } - d.fragmentedSize += len(pkt.Payload[2:]) - if d.fragmentedSize > h264.MaxNALUSize { + d.fragmentsSize += len(pkt.Payload[2:]) + if d.fragmentsSize > h264.MaxNALUSize { d.fragments = d.fragments[:0] - return nil, 0, fmt.Errorf("NALU size (%d) is too big (maximum is %d)", d.fragmentedSize, h264.MaxNALUSize) + return nil, 0, fmt.Errorf("NALU size (%d) is too big, maximum is %d", d.fragmentsSize, h264.MaxNALUSize) } d.fragments = append(d.fragments, pkt.Payload[2:]) @@ -111,12 +111,12 @@ func (d *Decoder) Decode(pkt *rtp.Packet) ([][]byte, time.Duration, error) { return nil, 0, ErrMorePacketsNeeded } - nalus = [][]byte{joinFragments(d.fragments, d.fragmentedSize)} + nalus = [][]byte{joinFragments(d.fragments, d.fragmentsSize)} d.fragments = d.fragments[:0] case h264.NALUTypeSTAPA: - d.fragments = d.fragments[:0] // discard pending fragmented packets + d.fragments = d.fragments[:0] // discard pending fragments payload := pkt.Payload[1:] @@ -149,12 +149,12 @@ func (d *Decoder) Decode(pkt *rtp.Packet) ([][]byte, time.Duration, error) { case h264.NALUTypeSTAPB, h264.NALUTypeMTAP16, h264.NALUTypeMTAP24, h264.NALUTypeFUB: - d.fragments = d.fragments[:0] // discard pending fragmented packets + d.fragments = d.fragments[:0] // discard pending fragments d.firstPacketReceived = true return nil, 0, fmt.Errorf("packet type not supported (%v)", typ) default: - d.fragments = d.fragments[:0] // discard pending fragmented packets + d.fragments = d.fragments[:0] // discard pending fragments d.firstPacketReceived = true nalus = [][]byte{pkt.Payload} } diff --git a/pkg/formats/rtph264/encoder.go b/pkg/formats/rtph264/encoder.go index 3604103d..d07eb928 100644 --- a/pkg/formats/rtph264/encoder.go +++ b/pkg/formats/rtph264/encoder.go @@ -146,8 +146,10 @@ func (e *Encoder) writeSingle(nalu []byte, pts time.Duration, marker bool) ([]*r func (e *Encoder) writeFragmented(nalu []byte, pts time.Duration, marker bool) ([]*rtp.Packet, error) { // use only FU-A, not FU-B, since we always use non-interleaved mode // (packetization-mode=1) - packetCount := (len(nalu) - 1) / (e.PayloadMaxSize - 2) - lastPacketSize := (len(nalu) - 1) % (e.PayloadMaxSize - 2) + avail := e.PayloadMaxSize - 2 + le := len(nalu) - 1 + packetCount := le / avail + lastPacketSize := le % avail if lastPacketSize > 0 { packetCount++ } @@ -167,7 +169,7 @@ func (e *Encoder) writeFragmented(nalu []byte, pts time.Duration, marker bool) ( start = 1 } end := uint8(0) - le := e.PayloadMaxSize - 2 + le := avail if i == (packetCount - 1) { end = 1 le = lastPacketSize diff --git a/pkg/formats/rtph265/decoder.go b/pkg/formats/rtph265/decoder.go index 065e20bb..72c0c974 100644 --- a/pkg/formats/rtph265/decoder.go +++ b/pkg/formats/rtph265/decoder.go @@ -38,7 +38,7 @@ type Decoder struct { timeDecoder *rtptime.Decoder firstPacketReceived bool - fragmentedSize int + fragmentsSize int fragments [][]byte // for DecodeUntilMarker() @@ -57,7 +57,7 @@ func (d *Decoder) Decode(pkt *rtp.Packet) ([][]byte, time.Duration, error) { } if len(pkt.Payload) < 2 { - d.fragments = d.fragments[:0] // discard pending fragmented packets + d.fragments = d.fragments[:0] // discard pending fragments return nil, 0, fmt.Errorf("payload is too short") } @@ -66,7 +66,7 @@ func (d *Decoder) Decode(pkt *rtp.Packet) ([][]byte, time.Duration, error) { switch typ { case h265.NALUType_AggregationUnit: - d.fragments = d.fragments[:0] // discard pending fragmented packets + d.fragments = d.fragments[:0] // discard pending fragments payload := pkt.Payload[2:] @@ -98,7 +98,7 @@ func (d *Decoder) Decode(pkt *rtp.Packet) ([][]byte, time.Duration, error) { case h265.NALUType_FragmentationUnit: if len(pkt.Payload) < 3 { - d.fragments = d.fragments[:0] // discard pending fragmented packets + d.fragments = d.fragments[:0] // discard pending fragments return nil, 0, fmt.Errorf("payload is too short") } @@ -106,7 +106,7 @@ func (d *Decoder) Decode(pkt *rtp.Packet) ([][]byte, time.Duration, error) { end := (pkt.Payload[2] >> 6) & 0x01 if start == 1 { - d.fragments = d.fragments[:0] // discard pending fragmented packets + d.fragments = d.fragments[:0] // discard pending fragments if end != 0 { return nil, 0, fmt.Errorf("invalid fragmentation unit (can't contain both a start and end bit)") @@ -114,7 +114,7 @@ func (d *Decoder) Decode(pkt *rtp.Packet) ([][]byte, time.Duration, error) { typ := pkt.Payload[2] & 0b111111 head := uint16(pkt.Payload[0]&0b10000001)<<8 | uint16(typ)<<9 | uint16(pkt.Payload[1]) - d.fragmentedSize = len(pkt.Payload[1:]) + d.fragmentsSize = len(pkt.Payload[1:]) d.fragments = append(d.fragments, []byte{byte(head >> 8), byte(head)}, pkt.Payload[3:]) d.firstPacketReceived = true @@ -129,10 +129,10 @@ func (d *Decoder) Decode(pkt *rtp.Packet) ([][]byte, time.Duration, error) { return nil, 0, fmt.Errorf("invalid fragmentation unit (non-starting)") } - d.fragmentedSize += len(pkt.Payload[3:]) - if d.fragmentedSize > h265.MaxNALUSize { + d.fragmentsSize += len(pkt.Payload[3:]) + if d.fragmentsSize > h265.MaxNALUSize { d.fragments = d.fragments[:0] - return nil, 0, fmt.Errorf("NALU size (%d) is too big (maximum is %d)", d.fragmentedSize, h265.MaxNALUSize) + return nil, 0, fmt.Errorf("NALU size (%d) is too big, maximum is %d", d.fragmentsSize, h265.MaxNALUSize) } d.fragments = append(d.fragments, pkt.Payload[3:]) @@ -141,17 +141,17 @@ func (d *Decoder) Decode(pkt *rtp.Packet) ([][]byte, time.Duration, error) { return nil, 0, ErrMorePacketsNeeded } - nalus = [][]byte{joinFragments(d.fragments, d.fragmentedSize)} + nalus = [][]byte{joinFragments(d.fragments, d.fragmentsSize)} d.fragments = d.fragments[:0] case h265.NALUType_PACI: - d.fragments = d.fragments[:0] // discard pending fragmented packets + d.fragments = d.fragments[:0] // discard pending fragments d.firstPacketReceived = true return nil, 0, fmt.Errorf("PACI packets are not supported (yet)") default: - d.fragments = d.fragments[:0] // discard pending fragmented packets + d.fragments = d.fragments[:0] // discard pending fragments d.firstPacketReceived = true nalus = [][]byte{pkt.Payload} } diff --git a/pkg/formats/rtph265/encoder.go b/pkg/formats/rtph265/encoder.go index b8be0ce9..78c9920b 100644 --- a/pkg/formats/rtph265/encoder.go +++ b/pkg/formats/rtph265/encoder.go @@ -144,8 +144,10 @@ func (e *Encoder) writeSingle(nalu []byte, pts time.Duration, marker bool) ([]*r } func (e *Encoder) writeFragmentationUnits(nalu []byte, pts time.Duration, marker bool) ([]*rtp.Packet, error) { - n := (len(nalu) - 2) / (e.PayloadMaxSize - 3) - lastPacketSize := (len(nalu) - 2) % (e.PayloadMaxSize - 3) + avail := e.PayloadMaxSize - 3 + le := len(nalu) - 2 + n := le / avail + lastPacketSize := le % avail if lastPacketSize > 0 { n++ } @@ -162,7 +164,7 @@ func (e *Encoder) writeFragmentationUnits(nalu []byte, pts time.Duration, marker start = 1 } end := uint8(0) - le := e.PayloadMaxSize - 3 + le := avail if i == (n - 1) { end = 1 le = lastPacketSize diff --git a/pkg/formats/rtpmjpeg/decoder.go b/pkg/formats/rtpmjpeg/decoder.go index 4d3da2c5..d19d9f3e 100644 --- a/pkg/formats/rtpmjpeg/decoder.go +++ b/pkg/formats/rtpmjpeg/decoder.go @@ -108,7 +108,7 @@ func joinFragments(fragments [][]byte, size int) []byte { type Decoder struct { timeDecoder *rtptime.Decoder firstPacketReceived bool - fragmentedSize int + fragmentsSize int fragments [][]byte firstJpegHeader *headers.JPEG firstQTHeader *headers.QuantizationTable @@ -139,8 +139,8 @@ func (d *Decoder) Decode(pkt *rtp.Packet) ([]byte, time.Duration, error) { } if jh.FragmentOffset == 0 { - d.fragments = d.fragments[:0] // discard pending fragmented packets - d.fragmentedSize = 0 + d.fragments = d.fragments[:0] // discard pending fragments + d.fragmentsSize = 0 d.firstPacketReceived = true if jh.Quantization >= 128 { @@ -155,20 +155,20 @@ func (d *Decoder) Decode(pkt *rtp.Packet) ([]byte, time.Duration, error) { } d.fragments = append(d.fragments, byts) - d.fragmentedSize = len(byts) + d.fragmentsSize = len(byts) d.firstJpegHeader = &jh } else { - if int(jh.FragmentOffset) != d.fragmentedSize { + if int(jh.FragmentOffset) != d.fragmentsSize { if !d.firstPacketReceived { return nil, 0, ErrNonStartingPacketAndNoPrevious } - d.fragments = d.fragments[:0] // discard pending fragmented packets - d.fragmentedSize = 0 + d.fragments = d.fragments[:0] // discard pending fragments + d.fragmentsSize = 0 return nil, 0, fmt.Errorf("received wrong fragment") } - d.fragmentedSize += len(byts) + d.fragmentsSize += len(byts) d.fragments = append(d.fragments, byts) } @@ -176,14 +176,14 @@ func (d *Decoder) Decode(pkt *rtp.Packet) ([]byte, time.Duration, error) { return nil, 0, ErrMorePacketsNeeded } - if d.fragmentedSize < 2 { + if d.fragmentsSize < 2 { return nil, 0, fmt.Errorf("invalid data") } - data := joinFragments(d.fragments, d.fragmentedSize) + data := joinFragments(d.fragments, d.fragmentsSize) d.fragments = d.fragments[:0] - d.fragmentedSize = 0 + d.fragmentsSize = 0 var buf []byte diff --git a/pkg/formats/rtpmpeg2audio/decoder.go b/pkg/formats/rtpmpeg2audio/decoder.go index d34489ca..797998ab 100644 --- a/pkg/formats/rtpmpeg2audio/decoder.go +++ b/pkg/formats/rtpmpeg2audio/decoder.go @@ -36,7 +36,7 @@ type Decoder struct { timeDecoder *rtptime.Decoder firstPacketReceived bool fragments [][]byte - fragmentedSize int + fragmentsSize int fragmentsExpected int } @@ -48,15 +48,15 @@ func (d *Decoder) Init() { // Decode decodes frames from a RTP packet. func (d *Decoder) Decode(pkt *rtp.Packet) ([][]byte, time.Duration, error) { if len(pkt.Payload) < 5 { - d.fragments = d.fragments[:0] // discard pending fragmented packets - d.fragmentedSize = 0 + d.fragments = d.fragments[:0] // discard pending fragments + d.fragmentsSize = 0 return nil, 0, fmt.Errorf("payload is too short") } mbz := uint16(pkt.Payload[0])<<8 | uint16(pkt.Payload[1]) if mbz != 0 { - d.fragments = d.fragments[:0] // discard pending fragmented packets - d.fragmentedSize = 0 + d.fragments = d.fragments[:0] // discard pending fragments + d.fragmentsSize = 0 return nil, 0, fmt.Errorf("invalid MBZ: %v", mbz) } @@ -65,8 +65,8 @@ func (d *Decoder) Decode(pkt *rtp.Packet) ([][]byte, time.Duration, error) { var frames [][]byte if offset == 0 { - d.fragments = d.fragments[:0] // discard pending fragmented packets - d.fragmentedSize = 0 + d.fragments = d.fragments[:0] // discard pending fragments + d.fragmentsSize = 0 d.firstPacketReceived = true buf := pkt.Payload[4:] @@ -91,29 +91,29 @@ func (d *Decoder) Decode(pkt *rtp.Packet) ([][]byte, time.Duration, error) { } d.fragments = append(d.fragments, buf) - d.fragmentedSize = bl + d.fragmentsSize = bl d.fragmentsExpected = fl - bl return nil, 0, ErrMorePacketsNeeded } } } else { - if int(offset) != d.fragmentedSize { + if int(offset) != d.fragmentsSize { if !d.firstPacketReceived { return nil, 0, ErrNonStartingPacketAndNoPrevious } - d.fragments = d.fragments[:0] // discard pending fragmented packets - d.fragmentedSize = 0 - return nil, 0, fmt.Errorf("unexpected offset %v, expected %v", offset, d.fragmentedSize) + d.fragments = d.fragments[:0] // discard pending fragments + d.fragmentsSize = 0 + return nil, 0, fmt.Errorf("unexpected offset %v, expected %v", offset, d.fragmentsSize) } bl := len(pkt.Payload[4:]) - d.fragmentedSize += bl + d.fragmentsSize += bl d.fragmentsExpected -= bl if d.fragmentsExpected < 0 { - d.fragments = d.fragments[:0] // discard pending fragmented packets - d.fragmentedSize = 0 + d.fragments = d.fragments[:0] // discard pending fragments + d.fragmentsSize = 0 return nil, 0, fmt.Errorf("fragment is too big") } @@ -123,10 +123,10 @@ func (d *Decoder) Decode(pkt *rtp.Packet) ([][]byte, time.Duration, error) { return nil, 0, ErrMorePacketsNeeded } - frames = [][]byte{joinFragments(d.fragments, d.fragmentedSize)} + frames = [][]byte{joinFragments(d.fragments, d.fragmentsSize)} d.fragments = d.fragments[:0] - d.fragmentedSize = 0 + d.fragmentsSize = 0 } return frames, d.timeDecoder.Decode(pkt.Timestamp), nil diff --git a/pkg/formats/rtpmpeg2audio/encoder.go b/pkg/formats/rtpmpeg2audio/encoder.go index 8f35d64c..b9916b9f 100644 --- a/pkg/formats/rtpmpeg2audio/encoder.go +++ b/pkg/formats/rtpmpeg2audio/encoder.go @@ -125,10 +125,10 @@ func (e *Encoder) writeBatch(frames [][]byte, pts time.Duration) ([]*rtp.Packet, } func (e *Encoder) writeFragmented(frame []byte, pts time.Duration) ([]*rtp.Packet, error) { - availPerPacket := e.PayloadMaxSize - 4 + avail := e.PayloadMaxSize - 4 le := len(frame) - packetCount := le / availPerPacket - lastPacketSize := le % availPerPacket + packetCount := le / avail + lastPacketSize := le % avail if lastPacketSize > 0 { packetCount++ } @@ -140,7 +140,7 @@ func (e *Encoder) writeFragmented(frame []byte, pts time.Duration) ([]*rtp.Packe for i := range ret { var le int if i != (packetCount - 1) { - le = availPerPacket + le = avail } else { le = lastPacketSize } diff --git a/pkg/formats/rtpmpeg4audio/decoder.go b/pkg/formats/rtpmpeg4audio/decoder.go index cbff3c72..c4af7133 100644 --- a/pkg/formats/rtpmpeg4audio/decoder.go +++ b/pkg/formats/rtpmpeg4audio/decoder.go @@ -39,11 +39,11 @@ type Decoder struct { // The number of bits in which the AU-Index-delta field is encoded in any non-first AU-header. IndexDeltaLength int - timeDecoder *rtptime.Decoder - firstAUParsed bool - adtsMode bool - fragments [][]byte - fragmentedSize int + timeDecoder *rtptime.Decoder + firstAUParsed bool + adtsMode bool + fragments [][]byte + fragmentsSize int } // Init initializes the decoder. @@ -56,14 +56,14 @@ func (d *Decoder) Init() { // The PTS of subsequent AUs can be calculated by adding time.Second*mpeg4audio.SamplesPerAccessUnit/clockRate. func (d *Decoder) Decode(pkt *rtp.Packet) ([][]byte, time.Duration, error) { if len(pkt.Payload) < 2 { - d.fragments = d.fragments[:0] // discard pending fragmented packets + d.fragments = d.fragments[:0] // discard pending fragments return nil, 0, fmt.Errorf("payload is too short") } // AU-headers-length (16 bits) headersLen := int(uint16(pkt.Payload[0])<<8 | uint16(pkt.Payload[1])) if headersLen == 0 { - d.fragments = d.fragments[:0] // discard pending fragmented packets + d.fragments = d.fragments[:0] // discard pending fragments return nil, 0, fmt.Errorf("invalid AU-headers-length") } payload := pkt.Payload[2:] @@ -71,7 +71,7 @@ func (d *Decoder) Decode(pkt *rtp.Packet) ([][]byte, time.Duration, error) { // AU-headers dataLens, err := d.readAUHeaders(payload, headersLen) if err != nil { - d.fragments = d.fragments[:0] // discard pending fragmented packets + d.fragments = d.fragments[:0] // discard pending fragments return nil, 0, err } @@ -104,26 +104,26 @@ func (d *Decoder) Decode(pkt *rtp.Packet) ([][]byte, time.Duration, error) { return nil, 0, fmt.Errorf("payload is too short") } - d.fragmentedSize = int(dataLens[0]) + d.fragmentsSize = int(dataLens[0]) d.fragments = append(d.fragments, payload[:dataLens[0]]) return nil, 0, ErrMorePacketsNeeded } } else { // we are decoding a fragmented AU if len(dataLens) != 1 { - d.fragments = d.fragments[:0] // discard pending fragmented packets + d.fragments = d.fragments[:0] // discard pending fragments return nil, 0, fmt.Errorf("a fragmented packet can only contain one AU") } if len(payload) < int(dataLens[0]) { - d.fragments = d.fragments[:0] // discard pending fragmented packets + d.fragments = d.fragments[:0] // discard pending fragments return nil, 0, fmt.Errorf("payload is too short") } - d.fragmentedSize += int(dataLens[0]) - if d.fragmentedSize > mpeg4audio.MaxAccessUnitSize { - d.fragments = d.fragments[:0] // discard pending fragmented packets - return nil, 0, fmt.Errorf("AU size (%d) is too big (maximum is %d)", d.fragmentedSize, mpeg4audio.MaxAccessUnitSize) + d.fragmentsSize += int(dataLens[0]) + if d.fragmentsSize > mpeg4audio.MaxAccessUnitSize { + d.fragments = d.fragments[:0] // discard pending fragments + return nil, 0, fmt.Errorf("AU size (%d) is too big, maximum is %d", d.fragmentsSize, mpeg4audio.MaxAccessUnitSize) } d.fragments = append(d.fragments, payload[:dataLens[0]]) @@ -132,7 +132,7 @@ func (d *Decoder) Decode(pkt *rtp.Packet) ([][]byte, time.Duration, error) { return nil, 0, ErrMorePacketsNeeded } - aus = [][]byte{joinFragments(d.fragments, d.fragmentedSize)} + aus = [][]byte{joinFragments(d.fragments, d.fragmentsSize)} d.fragments = d.fragments[:0] } diff --git a/pkg/formats/rtpmpeg4audio/encoder.go b/pkg/formats/rtpmpeg4audio/encoder.go index eb9f6d64..a6f269a7 100644 --- a/pkg/formats/rtpmpeg4audio/encoder.go +++ b/pkg/formats/rtpmpeg4audio/encoder.go @@ -132,10 +132,10 @@ func (e *Encoder) writeFragmented(au []byte, pts time.Duration) ([]*rtp.Packet, auHeadersLenBytes++ } - auMaxSize := e.PayloadMaxSize - 2 - auHeadersLenBytes + avail := e.PayloadMaxSize - 2 - auHeadersLenBytes le := len(au) - packetCount := le / auMaxSize - lastPacketSize := le % auMaxSize + packetCount := le / avail + lastPacketSize := le % avail if lastPacketSize > 0 { packetCount++ } @@ -146,7 +146,7 @@ func (e *Encoder) writeFragmented(au []byte, pts time.Duration) ([]*rtp.Packet, for i := range ret { var le int if i != (packetCount - 1) { - le = auMaxSize + le = avail } else { le = lastPacketSize } diff --git a/pkg/formats/rtpmpeg4video/decoder.go b/pkg/formats/rtpmpeg4video/decoder.go index c71b09d2..4cd64bad 100644 --- a/pkg/formats/rtpmpeg4video/decoder.go +++ b/pkg/formats/rtpmpeg4video/decoder.go @@ -29,9 +29,9 @@ func joinFragments(fragments [][]byte, size int) []byte { // Decoder is a RTP/MPEG-4 Video decoder. // Specification: https://datatracker.ietf.org/doc/html/rfc6416 type Decoder struct { - timeDecoder *rtptime.Decoder - fragments [][]byte - fragmentedSize int + timeDecoder *rtptime.Decoder + fragments [][]byte + fragmentsSize int } // Init initializes the decoder. @@ -47,15 +47,15 @@ func (d *Decoder) Decode(pkt *rtp.Packet) ([]byte, time.Duration, error) { if pkt.Marker { frame = pkt.Payload } else { - d.fragmentedSize = len(pkt.Payload) + d.fragmentsSize = len(pkt.Payload) d.fragments = append(d.fragments, pkt.Payload) return nil, 0, ErrMorePacketsNeeded } } else { - d.fragmentedSize += len(pkt.Payload) - if d.fragmentedSize > maxFrameSize { - d.fragments = d.fragments[:0] // discard pending fragmented packets - return nil, 0, fmt.Errorf("frame size (%d) is too big (maximum is %d)", d.fragmentedSize, maxFrameSize) + d.fragmentsSize += len(pkt.Payload) + if d.fragmentsSize > maxFrameSize { + d.fragments = d.fragments[:0] // discard pending fragments + return nil, 0, fmt.Errorf("frame size (%d) is too big, maximum is %d", d.fragmentsSize, maxFrameSize) } d.fragments = append(d.fragments, pkt.Payload) @@ -64,7 +64,7 @@ func (d *Decoder) Decode(pkt *rtp.Packet) ([]byte, time.Duration, error) { return nil, 0, ErrMorePacketsNeeded } - frame = joinFragments(d.fragments, d.fragmentedSize) + frame = joinFragments(d.fragments, d.fragmentsSize) d.fragments = d.fragments[:0] } diff --git a/pkg/formats/rtpmpeg4video/encoder.go b/pkg/formats/rtpmpeg4video/encoder.go index d0975186..d36930cc 100644 --- a/pkg/formats/rtpmpeg4video/encoder.go +++ b/pkg/formats/rtpmpeg4video/encoder.go @@ -69,10 +69,10 @@ func (e *Encoder) Init() { // Encode encodes a frame into RTP packets. func (e *Encoder) Encode(frame []byte, pts time.Duration) ([]*rtp.Packet, error) { - availPerPacket := e.PayloadMaxSize + avail := e.PayloadMaxSize le := len(frame) - packetCount := le / availPerPacket - lastPacketSize := le % availPerPacket + packetCount := le / avail + lastPacketSize := le % avail if lastPacketSize > 0 { packetCount++ } @@ -84,7 +84,7 @@ func (e *Encoder) Encode(frame []byte, pts time.Duration) ([]*rtp.Packet, error) for i := range ret { var le int if i != (packetCount - 1) { - le = availPerPacket + le = avail } else { le = lastPacketSize } diff --git a/pkg/formats/rtpvp8/decoder.go b/pkg/formats/rtpvp8/decoder.go index 44d7ea8c..60cd6b00 100644 --- a/pkg/formats/rtpvp8/decoder.go +++ b/pkg/formats/rtpvp8/decoder.go @@ -48,19 +48,19 @@ func (d *Decoder) Decode(pkt *rtp.Packet) ([]byte, time.Duration, error) { var vpkt codecs.VP8Packet _, err := vpkt.Unmarshal(pkt.Payload) if err != nil { - d.fragments = d.fragments[:0] // discard pending fragmented packets + d.fragments = d.fragments[:0] // discard pending fragments return nil, 0, err } if vpkt.PID != 0 { - d.fragments = d.fragments[:0] // discard pending fragmented packets + d.fragments = d.fragments[:0] // discard pending fragments return nil, 0, fmt.Errorf("packets containing single partitions are not supported") } var frame []byte if vpkt.S == 1 { - d.fragments = d.fragments[:0] // discard pending fragmented packets + d.fragments = d.fragments[:0] // discard pending fragments d.firstPacketReceived = true if !pkt.Marker { diff --git a/pkg/formats/rtpvp9/decoder.go b/pkg/formats/rtpvp9/decoder.go index 46fb9fb3..d8b3ecd1 100644 --- a/pkg/formats/rtpvp9/decoder.go +++ b/pkg/formats/rtpvp9/decoder.go @@ -48,14 +48,14 @@ func (d *Decoder) Decode(pkt *rtp.Packet) ([]byte, time.Duration, error) { var vpkt codecs.VP9Packet _, err := vpkt.Unmarshal(pkt.Payload) if err != nil { - d.fragments = d.fragments[:0] // discard pending fragmented packets + d.fragments = d.fragments[:0] // discard pending fragments return nil, 0, err } var frame []byte if vpkt.B { - d.fragments = d.fragments[:0] // discard pending fragmented packets + d.fragments = d.fragments[:0] // discard pending fragments d.firstPacketReceived = true if !vpkt.E { diff --git a/pkg/formats/vp9.go b/pkg/formats/vp9.go index 5521fce8..a19d31d3 100644 --- a/pkg/formats/vp9.go +++ b/pkg/formats/vp9.go @@ -1,4 +1,4 @@ -package formats +package formats //nolint:dupl import ( "fmt"