Skip to content

Commit c9b91e6

Browse files
authored
improve AV1 decoder efficiency (#744)
1 parent 3414414 commit c9b91e6

File tree

6 files changed

+57
-43
lines changed

6 files changed

+57
-43
lines changed

pkg/format/rtpav1/decoder.go

+45-36
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66

77
"github.com/bluenviron/mediacommon/v2/pkg/codecs/av1"
88
"github.com/pion/rtp"
9-
"github.com/pion/rtp/codecs"
109
)
1110

1211
// ErrMorePacketsNeeded is returned when more packets are needed.
@@ -61,20 +60,35 @@ func (d *Decoder) resetFragments() {
6160
}
6261

6362
func (d *Decoder) decodeOBUs(pkt *rtp.Packet) ([][]byte, error) {
64-
var av1header codecs.AV1Packet
65-
_, err := av1header.Unmarshal(pkt.Payload)
66-
if err != nil {
67-
d.resetFragments()
68-
return nil, fmt.Errorf("invalid header: %w", err)
63+
if len(pkt.Payload) < 2 {
64+
return nil, fmt.Errorf("invalid payload size")
6965
}
7066

71-
for _, obu := range av1header.OBUElements {
72-
if len(obu) == 0 {
73-
return nil, fmt.Errorf("invalid OBU size")
67+
z := (pkt.Payload[0] & 0b10000000) != 0
68+
y := (pkt.Payload[0] & 0b01000000) != 0
69+
payload := pkt.Payload[1:]
70+
var obus [][]byte
71+
72+
for len(payload) > 0 {
73+
var size av1.LEB128
74+
n, err := size.Unmarshal(payload)
75+
if err != nil {
76+
d.resetFragments()
77+
return nil, err
7478
}
79+
payload = payload[n:]
80+
81+
if size == 0 || len(payload) < int(size) {
82+
return nil, fmt.Errorf("invalid fragmented OBU (invalid size)")
83+
}
84+
85+
var obu []byte
86+
obu, payload = payload[:size], payload[size:]
87+
obus = append(obus, obu)
7588
}
7689

77-
if av1header.Z {
90+
// first OBU is continuation of previous one
91+
if z {
7892
if d.fragmentsSize == 0 {
7993
if !d.firstPacketReceived {
8094
return nil, ErrNonStartingPacketAndNoPrevious
@@ -83,12 +97,14 @@ func (d *Decoder) decodeOBUs(pkt *rtp.Packet) ([][]byte, error) {
8397
return nil, fmt.Errorf("received a subsequent fragment without previous fragments")
8498
}
8599

100+
d.firstPacketReceived = true
101+
86102
if pkt.SequenceNumber != d.fragmentNextSeqNum {
87103
d.resetFragments()
88104
return nil, fmt.Errorf("discarding frame since a RTP packet is missing")
89105
}
90106

91-
d.fragmentsSize += len(av1header.OBUElements[0])
107+
d.fragmentsSize += len(obus[0])
92108

93109
if d.fragmentsSize > av1.MaxTemporalUnitSize {
94110
errSize := d.fragmentsSize
@@ -97,38 +113,31 @@ func (d *Decoder) decodeOBUs(pkt *rtp.Packet) ([][]byte, error) {
97113
errSize, av1.MaxTemporalUnitSize)
98114
}
99115

100-
d.fragments = append(d.fragments, av1header.OBUElements[0])
101-
av1header.OBUElements = av1header.OBUElements[1:]
116+
d.fragments = append(d.fragments, obus[0])
102117
d.fragmentNextSeqNum++
103-
}
104-
105-
d.firstPacketReceived = true
106118

107-
var obus [][]byte
108-
109-
if len(av1header.OBUElements) > 0 {
110-
if d.fragmentsSize != 0 {
111-
obus = append(obus, joinFragments(d.fragments, d.fragmentsSize))
112-
d.resetFragments()
113-
}
114-
115-
if av1header.Y {
116-
elementCount := len(av1header.OBUElements)
117-
118-
d.fragmentsSize = len(av1header.OBUElements[elementCount-1])
119-
d.fragments = append(d.fragments, av1header.OBUElements[elementCount-1])
120-
av1header.OBUElements = av1header.OBUElements[:elementCount-1]
121-
d.fragmentNextSeqNum = pkt.SequenceNumber + 1
119+
if len(obus) == 1 && y {
120+
return nil, ErrMorePacketsNeeded
122121
}
123122

124-
obus = append(obus, av1header.OBUElements...)
125-
} else if !av1header.Y {
126-
obus = append(obus, joinFragments(d.fragments, d.fragmentsSize))
123+
obus[0] = joinFragments(d.fragments, d.fragmentsSize)
127124
d.resetFragments()
125+
} else {
126+
d.firstPacketReceived = true
128127
}
129128

130-
if len(obus) == 0 {
131-
return nil, ErrMorePacketsNeeded
129+
// last OBU will continue in next packet
130+
if y {
131+
var obu []byte
132+
obu, obus = obus[len(obus)-1], obus[:len(obus)-1]
133+
134+
d.fragmentsSize = len(obu)
135+
d.fragments = append(d.fragments, obu)
136+
d.fragmentNextSeqNum = pkt.SequenceNumber + 1
137+
138+
if len(obus) == 0 {
139+
return nil, ErrMorePacketsNeeded
140+
}
132141
}
133142

134143
return obus, nil

pkg/format/rtpav1/testdata/fuzz/FuzzDecoder/1fd6e8e69fb31947

-5
This file was deleted.

pkg/format/rtpav1/testdata/fuzz/FuzzDecoder/18413e36c51d1ebe pkg/format/rtpav1/testdata/fuzz/FuzzDecoder/894f7b51b885dbb1

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ go test fuzz v1
22
[]byte("0\x00")
33
bool(true)
44
[]byte("0")
5-
bool(true)
5+
bool(false)
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
go test fuzz v1
2-
[]byte("\xd00")
2+
[]byte("\xb0\x010")
33
bool(false)
44
[]byte("0")
55
bool(false)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
go test fuzz v1
2+
[]byte("0\xbb")
3+
bool(true)
4+
[]byte("0")
5+
bool(false)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
go test fuzz v1
2+
[]byte("00")
3+
bool(true)
4+
[]byte("0")
5+
bool(true)

0 commit comments

Comments
 (0)