123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- package rtcp
- import (
- "encoding/binary"
- )
- // PacketType specifies the type of an RTCP packet
- type PacketType uint8
- // RTCP packet types registered with IANA. See: https://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml#rtp-parameters-4
- const (
- TypeSenderReport PacketType = 200 // RFC 3550, 6.4.1
- TypeReceiverReport PacketType = 201 // RFC 3550, 6.4.2
- TypeSourceDescription PacketType = 202 // RFC 3550, 6.5
- TypeGoodbye PacketType = 203 // RFC 3550, 6.6
- TypeApplicationDefined PacketType = 204 // RFC 3550, 6.7 (unimplemented)
- TypeTransportSpecificFeedback PacketType = 205 // RFC 4585, 6051
- TypePayloadSpecificFeedback PacketType = 206 // RFC 4585, 6.3
- TypeExtendedReport PacketType = 207 // RFC 3611
- )
- // Transport and Payload specific feedback messages overload the count field to act as a message type. those are listed here
- const (
- FormatSLI uint8 = 2
- FormatPLI uint8 = 1
- FormatFIR uint8 = 4
- FormatTLN uint8 = 1
- FormatRRR uint8 = 5
- FormatCCFB uint8 = 11
- FormatREMB uint8 = 15
- // https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01#page-5
- FormatTCC uint8 = 15
- )
- func (p PacketType) String() string {
- switch p {
- case TypeSenderReport:
- return "SR"
- case TypeReceiverReport:
- return "RR"
- case TypeSourceDescription:
- return "SDES"
- case TypeGoodbye:
- return "BYE"
- case TypeApplicationDefined:
- return "APP"
- case TypeTransportSpecificFeedback:
- return "TSFB"
- case TypePayloadSpecificFeedback:
- return "PSFB"
- case TypeExtendedReport:
- return "XR"
- default:
- return string(p)
- }
- }
- const rtpVersion = 2
- // A Header is the common header shared by all RTCP packets
- type Header struct {
- // If the padding bit is set, this individual RTCP packet contains
- // some additional padding octets at the end which are not part of
- // the control information but are included in the length field.
- Padding bool
- // The number of reception reports, sources contained or FMT in this packet (depending on the Type)
- Count uint8
- // The RTCP packet type for this packet
- Type PacketType
- // The length of this RTCP packet in 32-bit words minus one,
- // including the header and any padding.
- Length uint16
- }
- const (
- headerLength = 4
- versionShift = 6
- versionMask = 0x3
- paddingShift = 5
- paddingMask = 0x1
- countShift = 0
- countMask = 0x1f
- countMax = (1 << 5) - 1
- )
- // Marshal encodes the Header in binary
- func (h Header) Marshal() ([]byte, error) {
- /*
- * 0 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * |V=2|P| RC | PT=SR=200 | length |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
- rawPacket := make([]byte, headerLength)
- rawPacket[0] |= rtpVersion << versionShift
- if h.Padding {
- rawPacket[0] |= 1 << paddingShift
- }
- if h.Count > 31 {
- return nil, errInvalidHeader
- }
- rawPacket[0] |= h.Count << countShift
- rawPacket[1] = uint8(h.Type)
- binary.BigEndian.PutUint16(rawPacket[2:], h.Length)
- return rawPacket, nil
- }
- // Unmarshal decodes the Header from binary
- func (h *Header) Unmarshal(rawPacket []byte) error {
- if len(rawPacket) < headerLength {
- return errPacketTooShort
- }
- /*
- * 0 1 2 3
- * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- * |V=2|P| RC | PT | length |
- * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- */
- version := rawPacket[0] >> versionShift & versionMask
- if version != rtpVersion {
- return errBadVersion
- }
- h.Padding = (rawPacket[0] >> paddingShift & paddingMask) > 0
- h.Count = rawPacket[0] >> countShift & countMask
- h.Type = PacketType(rawPacket[1])
- h.Length = binary.BigEndian.Uint16(rawPacket[2:])
- return nil
- }
|