Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

make h264 nalu parsing optional #268

Merged
merged 2 commits into from
Apr 23, 2024
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
12 changes: 11 additions & 1 deletion codecs/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,18 @@ func (d *audioDepacketizer) IsPartitionHead(_ []byte) bool {
}

// videoDepacketizer is a mixin for video codec depacketizers
type videoDepacketizer struct{}
type videoDepacketizer struct {
zeroAllocation bool
}

func (d *videoDepacketizer) IsPartitionTail(marker bool, _ []byte) bool {
return marker
}

// SetZeroAllocation enables Zero Allocation mode for the depacketizer
// By default the Depacketizers will allocate as they parse. These allocations
// are needed for Metadata and other optional values. If you don't need this information
// enabling SetZeroAllocation gives you higher performance at a reduced feature set.
func (d *videoDepacketizer) SetZeroAllocation(zeroAllocation bool) {
d.zeroAllocation = zeroAllocation
}
26 changes: 18 additions & 8 deletions codecs/h264_packet.go
Original file line number Diff line number Diff line change
Expand Up @@ -188,14 +188,16 @@ type H264Packet struct {
videoDepacketizer
}

func (p *H264Packet) doPackaging(nalu []byte) []byte {
func (p *H264Packet) doPackaging(buf, nalu []byte) []byte {
if p.IsAVC {
naluLength := make([]byte, 4)
binary.BigEndian.PutUint32(naluLength, uint32(len(nalu)))
return append(naluLength, nalu...)
buf = binary.BigEndian.AppendUint32(buf, uint32(len(nalu)))
buf = append(buf, nalu...)
return buf
}

return append(annexbNALUStartCode, nalu...)
buf = append(buf, annexbNALUStartCode...)
buf = append(buf, nalu...)
return buf
}

// IsDetectedFinalPacketInSequence returns true of the packet passed in has the
Expand All @@ -206,6 +208,14 @@ func (p *H264Packet) IsDetectedFinalPacketInSequence(rtpPacketMarketBit bool) bo

// Unmarshal parses the passed byte slice and stores the result in the H264Packet this method is called upon
func (p *H264Packet) Unmarshal(payload []byte) ([]byte, error) {
if p.zeroAllocation {
return payload, nil
}

return p.parseBody(payload)
}

func (p *H264Packet) parseBody(payload []byte) ([]byte, error) {
if len(payload) == 0 {
return nil, fmt.Errorf("%w: %d <=0", errShortPacket, len(payload))
}
Expand All @@ -215,7 +225,7 @@ func (p *H264Packet) Unmarshal(payload []byte) ([]byte, error) {
naluType := payload[0] & naluTypeBitmask
switch {
case naluType > 0 && naluType < 24:
return p.doPackaging(payload), nil
return p.doPackaging(nil, payload), nil

case naluType == stapaNALUType:
currOffset := int(stapaHeaderSize)
Expand All @@ -228,7 +238,7 @@ func (p *H264Packet) Unmarshal(payload []byte) ([]byte, error) {
return nil, fmt.Errorf("%w STAP-A declared size(%d) is larger than buffer(%d)", errShortPacket, naluSize, len(payload)-currOffset)
}

result = append(result, p.doPackaging(payload[currOffset:currOffset+naluSize])...)
result = p.doPackaging(result, payload[currOffset:currOffset+naluSize])
currOffset += naluSize
}
return result, nil
Expand All @@ -251,7 +261,7 @@ func (p *H264Packet) Unmarshal(payload []byte) ([]byte, error) {
nalu := append([]byte{}, naluRefIdc|fragmentedNaluType)
nalu = append(nalu, p.fuaBuffer...)
p.fuaBuffer = nil
return p.doPackaging(nalu), nil
return p.doPackaging(nil, nalu), nil
}

return []byte{}, nil
Expand Down
4 changes: 4 additions & 0 deletions depacketizer.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@ package rtp

// Depacketizer depacketizes a RTP payload, removing any RTP specific data from the payload
type Depacketizer interface {
// Unmarshal parses the RTP payload and returns media.
// Metadata may be stored on the Depacketizer itself
Unmarshal(packet []byte) ([]byte, error)

// Checks if the packet is at the beginning of a partition. This
// should return false if the result could not be determined, in
// which case the caller will detect timestamp discontinuities.
IsPartitionHead(payload []byte) bool

// Checks if the packet is at the end of a partition. This should
// return false if the result could not be determined.
IsPartitionTail(marker bool, payload []byte) bool
Expand Down
Loading