|
- package aoiprxkit
-
- import (
- "encoding/binary"
- "errors"
- )
-
- type RTPPacket struct {
- Version uint8
- Padding bool
- Extension bool
- CSRCCount uint8
- Marker bool
- PayloadType uint8
- SequenceNumber uint16
- Timestamp uint32
- SSRC uint32
- Payload []byte
- }
-
- func ParseRTPPacket(buf []byte) (RTPPacket, error) {
- if len(buf) < 12 {
- return RTPPacket{}, errors.New("RTP packet too short")
- }
- b0 := buf[0]
- b1 := buf[1]
- p := RTPPacket{
- Version: b0 >> 6,
- Padding: (b0 & 0x20) != 0,
- Extension: (b0 & 0x10) != 0,
- CSRCCount: b0 & 0x0F,
- Marker: (b1 & 0x80) != 0,
- PayloadType: b1 & 0x7F,
- SequenceNumber: binary.BigEndian.Uint16(buf[2:4]),
- Timestamp: binary.BigEndian.Uint32(buf[4:8]),
- SSRC: binary.BigEndian.Uint32(buf[8:12]),
- }
- if p.Version != 2 {
- return RTPPacket{}, errors.New("unsupported RTP version")
- }
- headerLen := 12 + int(p.CSRCCount)*4
- if len(buf) < headerLen {
- return RTPPacket{}, errors.New("RTP packet too short for CSRC list")
- }
- if p.Extension {
- if len(buf) < headerLen+4 {
- return RTPPacket{}, errors.New("RTP packet too short for extension")
- }
- extLenWords := int(binary.BigEndian.Uint16(buf[headerLen+2 : headerLen+4]))
- headerLen += 4 + extLenWords*4
- if len(buf) < headerLen {
- return RTPPacket{}, errors.New("RTP packet too short for full extension")
- }
- }
- payload := buf[headerLen:]
- if p.Padding {
- if len(payload) == 0 {
- return RTPPacket{}, errors.New("RTP packet has invalid padding")
- }
- padLen := int(payload[len(payload)-1])
- if padLen <= 0 || padLen > len(payload) {
- return RTPPacket{}, errors.New("RTP packet has invalid pad length")
- }
- payload = payload[:len(payload)-padLen]
- }
- p.Payload = payload
- return p, nil
- }
|