mirror of
https://github.com/pion/webrtc.git
synced 2025-11-02 03:32:48 +08:00
119 lines
3.1 KiB
Go
119 lines
3.1 KiB
Go
package codecs
|
|
|
|
import "github.com/pions/webrtc/pkg/rtp"
|
|
|
|
// 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
|
|
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(packet *rtp.Packet) error {
|
|
payload := packet.Payload
|
|
|
|
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++
|
|
}
|
|
|
|
p.Payload = payload[payloadIndex:]
|
|
|
|
return nil
|
|
}
|