Skip to content

Commit

Permalink
Make parsing of the OBU list in AV1Packet optional
Browse files Browse the repository at this point in the history
In Pion, the (*XXXPacket).Unmarshal operation is supposed to be
fast and perform no allocation, as it is sometimes used to check
just a single flag in the packet header.  The AV1Packet
implementation breaks this property by parsing the whole list
of OBUs at Unmarshal time, even though it is likely to be unneeded.

The proper solution would be to remove the parsing of OBUs from
Unmarshal, for consistency with the other packet formats.
Unfortunately, this would break backwards compatibility.  We
therefore introduce a field DontParseOBUs which controls the
parsing.  Unfortunately, this means that the inefficient path
is the default, which smells really badly, but there's not much
we can do about it at this stage.
  • Loading branch information
jech committed Apr 15, 2024
1 parent 74a9dc7 commit 45b780f
Showing 1 changed file with 28 additions and 4 deletions.
32 changes: 28 additions & 4 deletions codecs/av1_packet.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,8 +131,15 @@ type AV1Packet struct {
// N: MUST be set to 1 if the packet is the first packet of a coded video sequence, and MUST be set to 0 otherwise.
N bool

// If true, don't populate the OBUElements field.
//
// Deprecated: this will become the default in a future version.
DontParseOBUElements bool

// Each AV1 RTP Packet is a collection of OBU Elements. Each OBU Element may be a full OBU, or just a fragment of one.
// AV1Frame provides the tools to construct a collection of OBUs from a collection of OBU Elements
//
// Deprecated: use the ParseOBUElements method instead.
OBUElements [][]byte
}

Expand All @@ -153,12 +160,29 @@ func (p *AV1Packet) Unmarshal(payload []byte) ([]byte, error) {
return nil, errIsKeyframeAndFragment
}

currentIndex := uint(1)
p.OBUElements = [][]byte{}
if !p.DontParseOBUElements {
elts, err := p.ParseOBUElements(payload[1:])
if err != nil {
return nil, err
}
p.OBUElements = elts
}

return payload[1:], nil
}

// Parse the OBUs in p
func (p *AV1Packet) ParseOBUElements(payload []byte) ([][]byte, error) {
if p.OBUElements != nil {
return p.OBUElements, nil
}

elts := [][]byte{}

var (
obuElementLength, bytesRead uint
err error
currentIndex uint = 0
)
for i := 1; ; i++ {
if currentIndex == uint(len(payload)) {
Expand All @@ -180,9 +204,9 @@ func (p *AV1Packet) Unmarshal(payload []byte) ([]byte, error) {
if uint(len(payload)) < currentIndex+obuElementLength {
return nil, errShortPacket
}
p.OBUElements = append(p.OBUElements, payload[currentIndex:currentIndex+obuElementLength])
elts = append(elts, payload[currentIndex:currentIndex+obuElementLength])
currentIndex += obuElementLength
}

return payload[1:], nil
return elts, nil
}

0 comments on commit 45b780f

Please sign in to comment.