Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions codecs/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,14 @@ func (d *videoDepacketizer) IsPartitionTail(marker bool, _ []byte) bool {
func (d *videoDepacketizer) SetZeroAllocation(zeroAllocation bool) {
d.zeroAllocation = zeroAllocation
}

// resizeUint16Slice resizes the provided slice to the desired size, or
// allocates a new slice if needed. The contents are unspecified; the
// caller must overwrite every element.
func resizeUint16Slice(s []uint16, desiredSize int) []uint16 {
if cap(s) >= desiredSize {
return s[:desiredSize]
}

return make([]uint16, desiredSize)
}
17 changes: 11 additions & 6 deletions codecs/vp9_packet.go
Original file line number Diff line number Diff line change
Expand Up @@ -452,8 +452,8 @@ func (p *VP9Packet) parseSSData(packet []byte, pos int) (int, error) { // nolint
p.NG = 0

if p.Y {
p.Width = make([]uint16, NS)
p.Height = make([]uint16, NS)
p.Width = resizeUint16Slice(p.Width, int(NS))
p.Height = resizeUint16Slice(p.Height, int(NS))
for i := 0; i < int(NS); i++ {
if len(packet) <= (pos + 3) {
return pos, errShortPacket
Expand Down Expand Up @@ -482,16 +482,21 @@ func (p *VP9Packet) parseSSData(packet []byte, pos int) (int, error) { // nolint

p.PGTID = append(p.PGTID, packet[pos]>>5)
p.PGU = append(p.PGU, packet[pos]&0x10 != 0)
R := (packet[pos] >> 2) & 0x3
reference := int((packet[pos] >> 2) & 0x3)
pos++

p.PGPDiff = append(p.PGPDiff, []uint8{})
if i >= cap(p.PGPDiff) {
p.PGPDiff = append(p.PGPDiff, []uint8{})
} else {
p.PGPDiff = p.PGPDiff[:i+1]
p.PGPDiff[i] = p.PGPDiff[i][:0]
}

if len(packet) <= (pos + int(R) - 1) {
if len(packet) <= (pos + reference - 1) {
return pos, errShortPacket
}

for j := 0; j < int(R); j++ {
for range reference {
p.PGPDiff[i] = append(p.PGPDiff[i], packet[pos])
pos++
}
Expand Down
51 changes: 51 additions & 0 deletions codecs/vp9_packet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,57 @@ func TestVP9Packet_Unmarshal(t *testing.T) {
}
}

// Two descriptors that populate every slice field.
// The first also carries layer info and uses 3 spatial layers; the
// second omits layer info and shrinks to 2 layers, so a reused packet must
// shed the first packet's extra layer and layer-info values.
//
//nolint:gochecknoglobals
var (
vp9SS3Layers = []byte{0xFE, 0x11, 0x51, 0x02, 0x58, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0x01, 0x14, 0x03, 0xAA}
vp9SS2Layers = []byte{0xDE, 0x12, 0x04, 0x38, 0, 7, 0, 8, 0, 9, 0, 10, 0x01, 0x14, 0x05, 0xBB}
)

// vp9TrimForReuse zeroes a VP9Packet while keeping its slices' capacity, the
// reset a reuse-oriented caller performs between Unmarshal calls.
func vp9TrimForReuse(p *VP9Packet) {
*p = VP9Packet{
PDiff: p.PDiff[:0],
Width: p.Width[:0],
Height: p.Height[:0],
PGTID: p.PGTID[:0],
PGU: p.PGU[:0],
PGPDiff: p.PGPDiff[:0],
}
}

// Unmarshalling into a reused VP9Packet must produce exactly the same packet
// as a fresh parse.
func TestVP9Packet_Unmarshal_ReusedPacket(t *testing.T) {
fresh := VP9Packet{}
_, err := fresh.Unmarshal(vp9SS2Layers)
assert.NoError(t, err)

// After a trim, every field must match a fresh parse.
reused := VP9Packet{}
_, err = reused.Unmarshal(vp9SS3Layers)
assert.NoError(t, err)
vp9TrimForReuse(&reused)
_, err = reused.Unmarshal(vp9SS2Layers)
assert.NoError(t, err)
assert.Equal(t, fresh, reused)
}

func TestVP9Packet_Unmarshal_ReusedPacketDoesNotAllocate(t *testing.T) {
p := VP9Packet{}
allocs := testing.AllocsPerRun(100, func() {
vp9TrimForReuse(&p)
_, err := p.Unmarshal(vp9SS3Layers)
assert.NoError(t, err)
})
assert.Zero(t, allocs)
}

func TestVP9Payloader_Payload(t *testing.T) {
r0 := int(rand.New(rand.NewSource(0)).Int31n(0x7FFF)) //nolint:gosec
var rands [][2]byte
Expand Down
Loading