diff options
Diffstat (limited to 'vendor/github.com/pion/rtp/codecs/vp8_packet.go')
-rw-r--r-- | vendor/github.com/pion/rtp/codecs/vp8_packet.go | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/vendor/github.com/pion/rtp/codecs/vp8_packet.go b/vendor/github.com/pion/rtp/codecs/vp8_packet.go new file mode 100644 index 0000000..7ade7da --- /dev/null +++ b/vendor/github.com/pion/rtp/codecs/vp8_packet.go @@ -0,0 +1,143 @@ +package codecs + +// VP8Payloader payloads VP8 packets +type VP8Payloader struct{} + +const ( + vp8HeaderSize = 1 +) + +// Payload fragments a VP8 packet across one or more byte arrays +func (p *VP8Payloader) Payload(mtu int, payload []byte) [][]byte { + /* + * https://tools.ietf.org/html/rfc7741#section-4.2 + * + * 0 1 2 3 4 5 6 7 + * +-+-+-+-+-+-+-+-+ + * |X|R|N|S|R| PID | (REQUIRED) + * +-+-+-+-+-+-+-+-+ + * X: |I|L|T|K| RSV | (OPTIONAL) + * +-+-+-+-+-+-+-+-+ + * I: |M| PictureID | (OPTIONAL) + * +-+-+-+-+-+-+-+-+ + * L: | TL0PICIDX | (OPTIONAL) + * +-+-+-+-+-+-+-+-+ + * T/K: |TID|Y| KEYIDX | (OPTIONAL) + * +-+-+-+-+-+-+-+-+ + * S: Start of VP8 partition. SHOULD be set to 1 when the first payload + * octet of the RTP packet is the beginning of a new VP8 partition, + * and MUST NOT be 1 otherwise. The S bit MUST be set to 1 for the + * first packet of each encoded frame. + */ + + maxFragmentSize := mtu - vp8HeaderSize + + payloadData := payload + payloadDataRemaining := len(payload) + + payloadDataIndex := 0 + var payloads [][]byte + + // Make sure the fragment/payload size is correct + if min(maxFragmentSize, payloadDataRemaining) <= 0 { + return payloads + } + for payloadDataRemaining > 0 { + currentFragmentSize := min(maxFragmentSize, payloadDataRemaining) + out := make([]byte, vp8HeaderSize+currentFragmentSize) + if payloadDataRemaining == len(payload) { + out[0] = 0x10 + } + + copy(out[vp8HeaderSize:], payloadData[payloadDataIndex:payloadDataIndex+currentFragmentSize]) + payloads = append(payloads, out) + + payloadDataRemaining -= currentFragmentSize + payloadDataIndex += currentFragmentSize + } + + return payloads +} + +// VP8Packet represents the VP8 header that is stored in the payload of an RTP Packet +type VP8Packet struct { + // Required Header + X uint8 /* extended controlbits present */ + N uint8 /* (non-reference frame) when set to 1 this frame can be discarded */ + S uint8 /* start of VP8 partition */ + PID uint8 /* partition index */ + + // Optional Header + I uint8 /* 1 if PictureID is present */ + L uint8 /* 1 if TL0PICIDX is present */ + T uint8 /* 1 if TID is present */ + K uint8 /* 1 if KEYIDX is present */ + PictureID uint16 /* 8 or 16 bits, picture ID */ + TL0PICIDX uint8 /* 8 bits temporal level zero index */ + + Payload []byte +} + +// Unmarshal parses the passed byte slice and stores the result in the VP8Packet this method is called upon +func (p *VP8Packet) Unmarshal(payload []byte) ([]byte, error) { + if payload == nil { + return nil, errNilPacket + } + + payloadLen := len(payload) + + if payloadLen < 4 { + return nil, errShortPacket + } + + payloadIndex := 0 + + p.X = (payload[payloadIndex] & 0x80) >> 7 + p.N = (payload[payloadIndex] & 0x20) >> 5 + p.S = (payload[payloadIndex] & 0x10) >> 4 + p.PID = payload[payloadIndex] & 0x07 + + payloadIndex++ + + if p.X == 1 { + p.I = (payload[payloadIndex] & 0x80) >> 7 + p.L = (payload[payloadIndex] & 0x40) >> 6 + p.T = (payload[payloadIndex] & 0x20) >> 5 + p.K = (payload[payloadIndex] & 0x10) >> 4 + payloadIndex++ + } + + if p.I == 1 { // PID present? + if payload[payloadIndex]&0x80 > 0 { // M == 1, PID is 16bit + payloadIndex += 2 + } else { + payloadIndex++ + } + } + + if p.L == 1 { + payloadIndex++ + } + + if p.T == 1 || p.K == 1 { + payloadIndex++ + } + + if payloadIndex >= payloadLen { + return nil, errShortPacket + } + p.Payload = payload[payloadIndex:] + return p.Payload, nil +} + +// VP8PartitionHeadChecker checks VP8 partition head +type VP8PartitionHeadChecker struct{} + +// IsPartitionHead checks whether if this is a head of the VP8 partition +func (*VP8PartitionHeadChecker) IsPartitionHead(packet []byte) bool { + p := &VP8Packet{} + if _, err := p.Unmarshal(packet); err != nil { + return false + } + return p.S == 1 +} |