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
17 changes: 12 additions & 5 deletions codecs/av1_packet.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ type AV1Payloader struct{}
// 5.3. https://aomediacodec.github.io/av1-spec/av1-spec.pdf#page=39
// Returns AV1 RTP packets https://aomediacodec.github.io/av1-rtp-spec/
// The payload is fragmented into multiple packets, each packet is a valid AV1 RTP payload.
// nolint:cyclop
// nolint:cyclop,gocognit
func (p *AV1Payloader) Payload(mtu uint16, payload []byte) (payloads [][]byte) {
// 2 is the minimum MTU for AV1 (aggregate header + 1 byte)
if mtu <= 1 || len(payload) == 0 {
Expand Down Expand Up @@ -72,6 +72,17 @@ func (p *AV1Payloader) Payload(mtu uint16, payload []byte) (payloads [][]byte) {
obuSize = len(payload) - offset
}

if obuSize > len(payload)-offset {
break
}

// padding carries no media and causes chromium to stall.
if obuHeader.Type == obu.OBUPadding {
offset += obuSize

continue
}

// Each RTP packet MUST NOT contain OBUs that belong to different temporal units.
// If a sequence header OBU is present in an RTP packet, then it SHOULD be the first OBU in the packet.
// https://aomediacodec.github.io/av1-rtp-spec/#5-packetization-rules
Expand All @@ -87,10 +98,6 @@ func (p *AV1Payloader) Payload(mtu uint16, payload []byte) (payloads [][]byte) {
currentPacketOBUHeader = obuHeader.ExtensionHeader
}

if obuSize > len(payload)-offset {
break
}

if len(currentOBUPayload) > 0 {
payloads, obusInPacket = p.appendOBUPayload(
payloads,
Expand Down
21 changes: 21 additions & 0 deletions codecs/av1_packet_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1166,6 +1166,27 @@ func TestAV1Payloader_HandleMTUBasedFragmentation(t *testing.T) {
testAV1TestRun(t, tests)
}

func TestAV1Payloader_Padding(t *testing.T) {
sequence := testAV1OBUPayload{
Header: &obu.Header{Type: obu.OBUSequenceHeader, HasSizeField: true},
Payload: []byte{0x01},
}
frame := testAV1OBUPayload{
Header: &obu.Header{Type: obu.OBUFrame, HasSizeField: true},
Payload: []byte{0x02},
}
padding := testAV1OBUPayload{
Header: &obu.Header{Type: obu.OBUPadding, HasSizeField: true},
Payload: make([]byte, 8192),
}
payloader := &AV1Payloader{}

assert.Empty(t, payloader.Payload(6, padding.Marshal()))
assert.Equal(t, [][]byte{{0x28, 0x02, 0x08, 0x01, 0x30, 0x02}},
payloader.Payload(6, (testAV1MultiOBUsPayload{padding, sequence, padding, frame, padding}).Marshal()),
)
}

func TestAV1Payloader_TemporalDelimiter(t *testing.T) {
tests := []testAV1Tests{
{
Expand Down
Loading